numbas / Numbas

A completely browser-based e-assessment/e-learning system, with an emphasis on mathematics
http://www.numbas.org.uk
Apache License 2.0
207 stars 122 forks source link

Make the HTMLAttached trigger behave as documented #736

Closed georgestagg closed 4 years ago

georgestagg commented 4 years ago

HTMLAttached does not currently behave as documented. When HTMLAttached triggers, the question.display.html property does not contain the individual question parts' HTML, even though each part's HTML is available in the part.display.html property.

This pull request rewrites HTMLAttached so that it triggers after we receive a descendantsComplete event from Knockout1, indicating that the DOM has finished binding. With this change question.display.html also contains each part's HTML when the HTMLAttached signal is triggered.

1: https://knockoutjs.com/documentation/binding-lifecycle-events.html

christianp commented 4 years ago

Does partsBound really fire when all the parts have been rendered? I would expect it to fire once the 'promise' binding has been applied, not once the promise itself has been resolved.

christianp commented 4 years ago

Yeah, descendantsComplete does indeed happen before the promise is resolved.

georgestagg commented 4 years ago

Ah, okay. With this change on my local installation I was able to access the part's HTML in the question.display.html property, so I thought descendantsComplete was calling partsBound after the parts had been rendered.

christianp commented 4 years ago

It turned out that descendantsComplete really does wait until the promise binding has finished. I've tidied this up in 7986f75fd5807e2, which gets rid of the partsHTMLAttached signal, and removes the dependency on all the parts' html_promises. There's now a descendantsComplete at the top of the question's HTML, which is used to trigger HTMLAttached.

I got stuck for ages because I didn't realise that the exam display's question list wasn't populated until HTMLAttached was triggered, which meant that if I waited for descendantsComplete to trigger HTMLAttached, the question's HTML was never attached to the page at all! The exam display now waits for the mainHTMLAttached signal, which is badly-named but is triggered when the HTML code for the question has been generated but not yet attached to the page.