A Conference Overview with XForms

Steven Pemberton, CWI Amsterdam

Version: 2019-05-20

Contents

  1. A Conference
  2. Abstracts
  3. Doing it with XForms
  4. Talks
  5. Instances
  6. Displaying the data
  7. List of tutorials
  8. Result
  9. The Talks
  10. The abstracts
  11. Switch
  12. Displaying an abstract
  13. Result
  14. Popping up
  15. Format
  16. Animation
  17. The Conference Program
  18. The Program
  19. Displaying the Program
  20. Result
  21. Add Authors and Abstracts
  22. Result
  23. Missing Talks
  24. Locating talks

A Conference

Consider this conference program overview:

A Conference Overview Page

Abstracts

The page contains all the content, including abstracts for the talks, with the use of several scripts to handle pop ups and so on.

The abstracts are initially hidden, but clicking on an "Abstract" button pops up the abstract for a talk:

Talk abstract pop-up

Doing it with XForms

The talks will be stored in two files, the tutorials:

<tutorials date="2019-06-17">
   <tutorial>
      <title>XProc 3.0</title>
      <author>Achim Berndzen</author>
      <author>Norman Walsh</author>
   </tutorial>
   <tutorial>
      <title>CSS Paged Media</title>
      <author>Tony Graham</author>
   </tutorial>
   <tutorial>
      <title>Declarative Applications with XForms</title>
      <author>Steven Pemberton</author>
   </tutorial>
</tutorials>

Talks

Similar for the talks, but with abstracts (elided here):

<talks>
   <talk>
      <title>&lt;Angle-brackets/&gt; on the Branch Line
             - (model) railway engineering with XML technologies</title>
      <abstract>
         <p>[Elided]</p>
      </abstract>
      <author>John Lumley (jwLResearch)*</author>
   </talk>
   <talk>
      <title>Documenting XML Structures</title>
      <abstract>
         <p>[Elided]</p>
      </abstract>
      <author>Erik Siegel (Xatapult)*</author>
   </talk>
   <talk>
      etc.

Instances

We create two instances to store that data:

<instance id="tutorials" src="tutorials.xml"/>
<instance id="talks"     src="talks.xml"/>

Since this is to be generic, so that it can also be used in future years, we've added a date to the top element of the tutorials data, and we should record that it is a date:

<bind ref="instance('tutorials')/@date" type="date"/>

Displaying the data

Beginning with the prelude.

The group element sets the context so that all enclosed references will by default be to data in the tutorials instance.

Since we don't know how many tutorials there will be each year we let XForms do the work, by outputting a count of the talks.

<group ref="instance('tutorials')">
   <label class="h2">Preconference Tutorials</label>
   The preconference day, <output ref="@date"/>, 
   will comprise of <output value="count(talk)"/>
   tutorial sessions by some of the world's foremost experts in their respective fields:

You'll see below that the format of the date output is adjusted to your localization.

List of tutorials

Now we can output the list of tutorials. Note that it deals with more than one author:

<repeat ref="talk">
   <output class="title" ref="title"/>
   <repeat ref="author">
      <output class="author" ref="."/>
   </repeat>
</repeat>

Result

which, with suitable CSS, looks like this:

Source

The Talks

These are treated fairly similarly, except we now want to add a button to display the abstract. It starts the same:

 <group ref="instance('talks')">
   <repeat ref="talk">
      <output class="title" ref="title"/>
      <repeat ref="author">
         <output class="author" ref="."/>
      </repeat>

The abstracts

Then comes the button to show the abstract:

   <trigger ref="abstract">
      <label>Abstract</label>
      <action ev:event="DOMActivate">
         <toggle case="show"/>
      </action>
   </trigger>

Attaching the trigger like this to the abstract (ref="abstract") ensures that if there is no abstract, there'll be no button.

When clicked on, or otherwise activated, a DOMActivate event is sent to the action element. This causes the toggle element to be processed.

Switch

The toggle element causes a case of a switch element to be activated.

Switch has a number of cases, only one of which is visible at a time.

Initially the first is visible, and a different one can be activated with a toggle.

In this case, we have a switch with two cases, one which shows nothing, and the other that shows the abstract:

   <switch>
      <case id="hide"/>
      <case id="show">
         ... this is where we display the abstract ...
      </case>
   </switch>

Displaying an abstract

To display the abstract, we repeat over the paragraphs of the data.

This is preceded by a trigger to hide the abstract again by activating the other case:

<group ref="abstract" class="abstract">
   <trigger>
      <label>X</label>
      <action ev:event="DOMActivate">
         <toggle case="hide"/>
      </action>
   </trigger>
   <repeat ref="p">
      <output class="p" ref="."/>
   </repeat>
</group>

Result

This looks like this:

Source

Popping up

This doesn't pop up the abstract, but just makes it visible. Should popping up be essential to the user experience, then we just change the CSS for that. You really don't need Javascript for these purposes:

Source

Format

If your complaint is that it is formatted differently to the original, well, we just change the CSS for that as well (this isn't a CSS tutorial, but if you need a hint, we've used display: inline-block).

Source

Animation

Finally, if a popping up animation is your thing, you can add that with a bit of CSS as well (Look up CSS animations to discover how this was done.)

Source

The Conference Program

Later, the conference changed the page to include the timings. Let's adapt.

The Conference Program

The Program

Our options here are

Let's do that.

The program consists of a number of days, and each day consists of a number of slots. A slot has a start and end time, and a title:

<program>
   <day which="Friday">
      <slot start="08:45" end="09:30">Registration</slot>
      <slot start="09:30" end="11:00">Declarative Applications with XForms</slot>
      <slot start="11:00" end="11:30">Break</slot>
      <slot start="11:30" end="13:00">XProc 3.0</slot>
      <slot start="13:00" end="14:00">Lunch</slot>
      <slot start="14:00" end="15:30">XProc 3.0 (cont'd)</slot>
      <slot start="15:30" end="16:00">Break</slot>
      <slot start="16:00" end="17:30">CSS Paged Media</slot>
   </day>
   <day which="Saturday">
      <slot start="08:45" end="09:30">Registration</slot>
      <slot start="09:30" end="10:15">Everyone Knows What a Dragon Looks Like</slot>

etc.

Displaying the Program

To display this we repeat over the days, and for each day, repeat over the slots:

<repeat ref="instance('program')/day">
   <output class="h2" value="@which"/>
   <repeat ref="slot">
      <output class="times" value="concat(@start, '-', @end)"/>
      <output class="entry" ref="."/>
   </repeat>
</repeat>

Result

Here's what this looks like:

Source

Add Authors and Abstracts

This of course is still missing the authors and the abstract. We get those from the talks instance by finding the talk whose title is the same as the entry in the slot, and then output the authors and abstract (in the same way as earlier):

<repeat ref="slot">
   <output class="times" value="concat(@start, '-', @end)"/>
   <group class="entry">
      <output class="title" ref="."/>
      <group ref="instance('talks')/talk[title=context()]">
         <repeat ref="author">
            <output class="author" ref="."/>
         </repeat>
         <trigger ref="abstract">
      ... etc ...

If no talk matches the condition, no talk will be selected, and so neither author nor abstract will be output.

(By the way, we've merged the tutorials instance, and the talks instance for simplicity in this version).

Result

Here's what it looks like:

Source

Missing Talks

One last thing: suppose that there is a talk that is in the talks document, but was forgotten in the program, or added twice by mistake. (We added a non-used talk to the talks file, which you can see at the bottom of the output above). To warn for that we repeat over the talks

<repeat ref="instance('talks')/talk">

and output only the titles that don't occur exactly once in the program:

<output class="warning" ref="title[...condition here...]"/>

Locating talks

How do we find out how many times a title occurs in a program?

We locate all slots in the program with that title:

instance('program')/day/slot[. = context()/title]

and then count them:

count(instance('program')/day/slot[. = context()/title])

That count should be 1.

In full:

<repeat ref="instance('talks')/talk">
   <output class="missing"
           ref="title[count(instance('program')/day/slot[
                                                  . = context()/title]) != 1]"/>
</repeat>

If there are no missing or duplicated talks, nothing will show up.