It used to be that my learning materials were transformed to ink on compressed cellulose sheets. Nowadays, I get to design an interactive experience where I can ask students to answer questions, trace code, compile and run programs, and draw diagrams instead of consuming them. There are many cool ways of providing those interactive experiences, and no good way of mixing and matching them. In this blog, I ruminate on my experience of delivering JavaScript-based learning activities in several learning environments, and what it might take to standardize that so that “mix and match” might become a reality. (It's not much.)
These days, when writing a textbook, we are not limited to bulleted lists, tables, and diagrams. Textbooks are nowadays delivered as EPUB or inside learning management systems, so anything that we can do with HTML, CSS, and JavaScript is fair game.
There are a few low-hanging fruit. It is simple to add video clips, animated diagrams, and multiple-choice quizzes. But we can do much more.
Here is a simple example: a “game” to teach the algorithm for finding the largest value in an array.
int i = 0; while (i < a.length) { if (i == 0 || a[i] > largest) largest = a[i]; i++; }
Each time, decide which of the three buttons to press. It is very hard to forget this algorithm after doing this exercise a few times.
I implemented this in a day, and a week later I had something much better—a framework where I can implement any number of these “games”. Here is one that teaches students how to shift elements out of the way when inserting a new element in the middle of an array.
if (c < values.length) //c
is the current size of the partially filled arrayv
{ c++; for (int i = c - 1; i > p; i--) // We will insert the new element atp
{ v[i] = v[i - 1]; } v[p] = newElement; }
Ok, now suppose you want to use my nifty interactive exercise in your course. Or maybe you want to use this Parsons Puzzle library. It is not too difficult to do that. After all, it's just HTML, CSS, and JavaScript.
But that's not good enough. How do you know whether your students are doing the activities? Whether they are doing them right? And what mistakes they make?
I know, I hear you say, just use LTI. That's what all the learning management systems (LMS) use.
LTI allows you to serve up contents that an LMS sticks in an iframe. The LMS tells your server the ID of the platform, course, activity, and student, and a URL to call back with a score (between 0.0 and 1.0). Your server renders the contents of the iframe and send the score to the LMS when the student is done.
Unfortunately, that's not very convenient when you want to use the LMS gradebook. If you have hundreds of little interactivities in the course—as I routinely do—then each of them turns into a column in the gradebook. That's not what teachers want. We want a “test bank” of activities from which we can form assignments, each consisting of multiple activities, with an aggregate score for the assignment and the ability to drill down into the student work. Will LMS vendors rise to the challenge to give us test banks with assignment types that let us place arbitrary LTI activities alongside multiple choice, fill in the blank, and its ilk? Maybe, but I am not holding my breath.
With my graduate students, I am working on an LTI provider called LTIHub that aggregates multiple activities into a single LTI activity.
I have also integrated my interactive elements into Engage (a Moodle-based learning platform used by Wiley), VitalSource (an EPUB platform), and Codio (an online programming platform for students). All four of these integrations required similar actions, and the remainder of this blog goes into the weeds of what they are. Most people should stop reading right now. If you need to solve a similar problem, or if you want to think about coming up with an interoperable standard, I am glad that you are still here.
An EPUB3 book is just HTML, CSS, and JavaScript in a ZIP file with table of contents and a “manifest” enumerating all resources. The EPUB3 standard poses some restrictions, most notably that the web pages must be XHTML.
EPUB for Education adds support for digital learning. What's of most interest here is support for score reporting and state saving. It couldn't be simpler.
Interactive JavaScript elements in an EPUB page call
EPUB.Education.reportScores(scores, callback);
where scores
is an array of objects of the form
{ score: number, location: string, metadata: {…} }
The location is a unique identifier of the activity. The metadata are anything that the activity wants to get back later when restoring scores and state.
The call
EPUB.Education.getScores(locationIDs, callback);
is used to retrieve scores and metadata. The callback receives an array of the same score data.
This provides three essential services.
Currently, this is implemented in VitalSource e-books. Codio has an API with exactly the same functionality but different calls. If you need to support multiple APIs of this type, it is easy enough to add a small indirection layer.
Conversely, if you build a viewer for student exercises, consider supporting this API.
When integrating with systems such as Moodle or LTIHub, it is convenient to place each interactive element in its own iframe. That way, the CSS and JavaScript resources of the element do not have to be merged into the container page, nor can they interfere with it. But there is a challenge—as the container page is responsible for managing student work, it needs to talk to the iframe. If the interactive elements are served up from a different source than the container page, there is only one way to talk to the iframe: Window.postMessage.
This is not a very convenient mechanism since it is asynchronous. The container sends a message to the interactive element, and the interactive element eventually sends a response back.
It is also easy to design this wrong—as we did in the LTIHub software where we periodically poll all interactive elements instead of waiting for them to report student progress to the container.
Here is what you want to do:
If interactive JavaScript elements can agree to support the EPUB for Education API, or a thin wrapper over it, then it is an easy matter to implement a generic wrapper around them that translates the API calls into Window.postMessage
invocations, in addition to generic support for size queries.
Again, my hope is “mix and match” of interactive JavaScript elements, authored by multiple people, in a single assignment or book page. There isn't much that needs to be standardized: receive state changes, restore last known state, size inquiry (for iframes).
One caveat: A purely JavaScript-based model is not suitable for high-stakes assessment. Anything that happens on the client is insecure and can be manipulated by those skilled in the art.
Comments powered by Talkyard.