We have created an SVG timeline with XQuery from the Digital Mitford letters collection stored in our eXist database. This is actually multiple timelines combined: One represents a total quantity of letters encoded in each year, and the others represent data about the timespans associated with specific correspondents in the collection.
We embedded this SVG in an HTML document, and associated it with CSS and JavaScript in order to control its layout and interactivity.
Here is how we put the pieces together.
Optimally, we want to generate our HTML page with SVG set within it, so that the same
XQuery functions generate the entire page. This is a bit of a challenge for outputting code
when working within multiple namespaces. Remember that we need to apply Q{}
in XPath within code
writtin in a different namespace, when you need to pull-process data from your project code.
<div id="svg">
or <section id="svg">
element (with the
namespace prefix if you prefixed HTML: <htm:div type="svg">
). You can set the dimensions of
the SVG viewport so that your timelines will fit on a screen on their own, and then as you incorporate them in the HTML,
apply CSS styling to adjust the dimensions of the div or section (for example, with CSS flexboxes). FLWOR
, we found we had to create two
for loops
over the set of distinct values of correspondents in the
collection, one placed near the top of the HTML page, and the other within the SVG
portion of the file. Note the following: <htm:input type="checkbox">
element to
generate our checkboxes, and we placed an @id
attribute on each one.
(To read more about HTML checkbox inputs, see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox
).Our checkbox basically just responds to a mouseclick, and with JavaScript we
will make the presence or absence of a check correspond with the display
properties of the corresponding SVG line. Note: You do not have to use a checkbox:
you could use a htm:button
or even an htm:span
element
that you might stylize in CSS. You simply need for the element to hold an
@id
attribute that corresponds to each member of your list of
distinct values. In order for that @id
value to be valid, you will
need to remove the hashtag from the front of the string retrieved from the TEI
@ref
attributes.for loop
to output SVG
<line>
and <text>
elements spaced down
the page, and we wrap these in an SVG <g>
, on which we place an
@id
attribute. However, we are not allowed to use the same
@id
value twice on the same document, so we wrote a short string
of prefixing text to distinguish one from the other. (We put SVG_
in
front of the distinct correspondent value identifying its group of SVG elements,
but we could just as easily have put something like HTM_
in front of
the @id
on the HTML input element.)$pos
variable in our XQuery for loop
: for $i at $pos in $variableWeAreLoopingThrough
..html
extension. script
element signalling your JavaScript file in
your XQuery script, in case you need to go back and alter the XQuery to correct your
HTML.html
root element:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"><oXygen/> should then give you a green light if all is well. Note: if there are hashtags (
#
) starting your @id attributes, these will raise an HTML
validation error: you want to avoid outputting those.In your JavaScript you will likely be doing some familiar things you have already tried, but you will face new challenges, too. Think about what needs to happen in sequence:
g
elements associated with particular correspondent
timelines. To toggle the display properties off and on involves writing JavaScript to
show or hide a particular line that the user is clicking on, that is, to change the
state from hidden to showing. In the CSS we set the default style for the correspondent
SVG g
elements (the ones on which we had set @id
attributes) to g[id] {display:none;}
. We then wrote a JavaScript
function to override that and return display="block"
, which is the proper
display value for SVG elements.init()
. That init()
or initial(
) function
should add event listeners on the HTML elements that you expect your site visitors to
interact with. This is familiar territory, but we found ourselves writing the element
selection a little differently than we have done in the past: In our SVG, we set
@id
attributes on each <input>
element. We could have
just used getElementsByTagName()
, but we thought we would show you a handy
selector in JavaScript that uses CSS syntax to identify elements that hold a
specific attribute called querySelectorAll()
: We wrote it like this
to define an array of elements:
var inputSelect = document.querySelectorAll('input[id]');That code creates an array of all the
<input>
elements that hold an
@id
attribute. After this we set up a JavaScript for-loop with the range
variable i
to step through each member of the array of
inputSelect.length
, and then we set up our
addEventListener()
to run on the inputSelect[i]
(or the
svgSelect variable at position i), and to fire the next function in sequence in the
event of 'click'
, just as you have already done on previous
assignments.function
init()
.This function needs to check the @id
value on the HTML
element that was clicked on, and to refer to that element, the one the user has just now
clicked on, we use the special JavaScript word this
. To find the
@id
on this
, we write: this.id
. What you need
to do with this.id
is use it to find the corresponding SVG element whose
@id
best matches. In our code, we added the string SVG_
, so
we sought out the element with the id 'SVG_' + this.id
to find the matching
group of SVG elements associated with a particular selected correspondent.if() else()
to change the display property of the matching SVG element. Remember that to check the
display condition of this
, we need to use the double equal sign:
==
, and use the single equal sign =
to indicate a change in
value.this
must first trigger another function that you write to make sure that the SVG elements are ALL hidden, before you trigger this
to be visible. This does not require JavaScript to test conditions: it simply turns off the display for a selection as soon as the user visits another selection. We have examples of both approaches on the DHClass-Hub for you to consult.