Improvements to the JSXGraph extension

Last week was the second International JSXGraph Conference. Numbas has had an extension to integrate JSXGraph for over 10 years, since the very start, but I haven’t done much with it, so I submitted a talk proposal to pressure myself into doing something.

That tactic worked – as the conference approached I spent a few days working on the extension, adding the ability to use JSXGraph diagrams in marking, just like you can with the GeoGebra extension.

Here’s the recording of my talk (and you can see the slides online, if you want to follow the links):

In the talk I laid out the main reasons I haven’t done much with JSXGraph:

  • Creating diagrams in JavaScript is fiddly: the syntax isn’t well-suited to it, and it’s easy to do things that aren’t robust: relying on undocumented features of the Numbas theme or external properties that can’t be easily detected, or not restoring the state of the diagram correctly when an attempt is resumed.
  • The interaction between diagrams and part inputs needs a lot of thought. While some things, like a point’s position linked to a pair of number inputs, are quite easy to describe, the link is often much easier to describe in one direction than the other.

The last time I looked at the JSXGraph extension, I added functions to create diagrams using JME code, or with JSXGraph’s built-in scripting language JessieCode. That removes a lot of brittle JavaScript and makes it loads easier to use randomised question variables in a diagram.

That just left marking and interaction with part inputs.

My first task was to make it possible to use properties of a JSXGraph diagram in a part’s marking algorithm. In order for this to work, the state of the diagram must be saved exactly, so when an attempt is resumed or opened in review mode it looks exactly as it did when the part was submitted. I discovered that JSXGraph has a “dump” mechanism for exactly this, but it only works if you don’t have any custom JavaScript – another reason to create diagrams exclusively through JME or JessieCode.

The extension now provides a few functions of the form jxg_property, which get values out of a diagram. For example, jxg_position(diagram["A"]) gets the position of the point A as a vector, and jxg_slope(diagram["L"]) gets the gradient of the line L.

Here’s a simple marking algorithm which checks that a point is in the required position:

student_pos: jxg_position(diagram["A"])

mark:
  correctif(student_pos=coords)

interpreted_answer: student_pos

This works for “extension” parts, where there’s no input box, so the marking is based entirely on the diagram.

Next, I tried a few different methods of linking a diagram to part inputs. The GeoGebra extension has a few built-in methods, based on the type of the part and the type of an object. This is quite limiting, so I wanted to do provide something a bit more versatile, while straightforward to understand and use.

I thought of a few examples of interaction where the input box contains a number derived from several objects in the diagram. A simple example is the slope of a line drawn between two points. What should happen when the student moves a point, and what should happen when they type in a slope that the line should have?

The model I’ve come up with is to define what happens for each direction separately, through notes in the part’s marking algorithm. There’s one note defining what to do to the diagram after the student changes their answer to the part’s input box, and another defining what to put in the input box when the diagram changes.

Here’s an example where you have to make a line cross the axes at certain points. You can drag the points on the graph, or type a slope in the box. When you type a slope, the points both move vertically around their midpoint. Is that the right thing to do? Alternately, we could:

  • Move just one point and move the other relative to it.
  • Place the points at $x=-1$ and $x=1$, and appropriate $y$ positions.
  • Move both points so the line crosses the vertical axis at the same point.

I also looked at accessibility. I prompted Alfred Wassermann, the lead developer of JSXGraph, to implement keyboard-only control. Fortunately Alfred already had this in his development plan, and quickly came up with a solution; thanks, Alfred! I’ve been submitting patches to improve keyboard control, which should be included in the next release of JSXGraph, but there’s still plenty to do. In particular, I’d like to see the ability to add ARIA labels to objects in diagrams, for assistive technology to read.

I’ve updated the demo exam for the JSXGraph extension to include a few examples using the new features, and I’ve recorded a video where I go through them, explain how they’re implemented, and then have a go at writing a question from scratch: