Picture of Ben S
Delaying course loading
by Ben S - Thursday, 31 July 2014, 1:48 PM
 

Hello,

I've forked the Spoor plugin and modified it so it saves and retrieves data from a simple API using Backbone.Sync rather than the SCORM API. This works fine for my needs, but I would like to delay the course from loading fully until the async call has returned. At the moment, the views load before the API returns and so the progress bars/completion statuses are incorrect. Does anyone have any suggestions on how this can be achieved? I've looked into the initialisation events but I'm not sure of the best place to hook in!

Thanks.

 

Picture of Ben S
Re: Delaying course loading
by Ben S - Tuesday, 5 August 2014, 8:37 AM
 

Can I be cheeky and bump this? My current workaround is to navigate back to the route menu when the fetch from the API has returned in order to reload the views, but I don't think that's the ideal way of doing it!

Picture of Chris Jones
Re: Delaying course loading
by Chris Jones - Tuesday, 5 August 2014, 10:15 AM
 

Hi Ben,

I'm pretty sure that there will need to be changes to the Core to support this.

There is currently no 'app:ready' event and therefore is no way to defer readiness from either the Core or a Plugin.

I think everything triggers off the 'app:dataLoaded' event instead, which fires as soon as the course is loaded.

Chris

 

 

 

 

 

Picture of Ben S
Re: Delaying course loading
by Ben S - Tuesday, 5 August 2014, 11:09 AM
 

Thanks Chris, I feared that would be the case. Navigating back to the homepage doesn't work either so I'll keep poking.

It seems like the ability to defer readiness to plugins would be useful generally? For instance, I'm not sure how loading from a SCORM or XAPI compatible LMS will work otherwise?

Picture of Chris Jones
Re: Delaying course loading
by Chris Jones - Tuesday, 5 August 2014, 12:04 PM
 

In an environment where the application is launching the course, the SCORM environment is generally already initialized, so its not been an issue in my experience. 

The way I could see it working is that the Core would need to fire a 'app:ready' event when the config & course has loaded _and_ all plugins have signaled ready.

Plugins could signal the Core by calling Adapt.deferReadiness() which would delay the 'app:ready' event until all have subsequently called .advance().

Then anything that required 'app:dataLoaded' would still work as intended, but the UI would wait on a new 'app:ready' event before continuing.

If I get some free time I might try exploring the possibility in a fork of the framework.

Gist

Picture of Daryl Hedley
Re: Delaying course loading
by Daryl Hedley - Wednesday, 6 August 2014, 10:20 AM
 

Hey Ben,

There's two ways you can do this:

1 - Call "Backbone.history.loadUrl();" after you've pulled your data down. This is not the recommend way of doing this as it would still download the original data. But maybe you might need this? Backbone is very good at comparing models and changing the new attributes only.

2 - Defer data loading through lockedAttributes - This is the preferred way to do it but will take a lot more work.

To achieve this you'll need to read the following information first to fully understand the system - I'd suggest this is an advanced feature of the framework and should be used in extreme cases. Now that the warning is out of the way:

Read this in order:

Core API

especially about the locked attributes

Core Events

Look at the following two events

configModel:dataLoaded and configModel:loadCourseData whilst bearing in mind this event

app:dataReady

 

To add to this information - you'll need to whitelist or blacklist certain attributes from the collections as you'll be carrying too much data too and from an API. To debug this - take a look at the Adapt object. Try and push it to the window in your modified Scorm plugin. If you're doing this - I'd suggest having an approach that uses both 1 and 2 above.

Once you understand all the above please read these lines in "src/core/js/models/configModel.js" - lines 31 to 42. Understanding what this does and the events triggered here will help you achieve that.

Are you trying to just push block tracking back?

Hope this helps!

Thanks,

Daryl

 

 

Picture of Ben S
Re: Delaying course loading
by Ben S - Wednesday, 6 August 2014, 1:41 PM
 

Thanks very much for the detailed suggestions. I think tapping into the core model attributes is going beyond what I need though, so sorry if I haven't explained myself very well.

When the plugin loads, it retrieves an array of the completed blocks (using Backbone's fetch and parse methods) from a remote API. It then loops through the completed blocks and sets them using block.set('_isComplete', true) - this bit is copied directly from the Spoor plugin :). I'm able to inspect the models using the Backbone Debugger extension for Chrome and verify that they are indeed being set properly. When further blocks are completed, I've tapped into the change:_isComplete event and use the Backbone save method to save back to the remote API. This all seems to work ok.

My particular problem is that when the course loads the blocks are being updated by my plugin after the views (particularly the menu view) have been rendered. The getCompleteComponentsAsPercentage value is already set and therefore the user doesn't see which content objects they've already completed. Alternatively, if something goes wrong with the API call the course still loads, which is fine for now but I'd like the flexibility of blocking it. Ideally the whole course would sit at "loading..." until the api call is complete, but I think from Chris' comments that that's impossible at present.

I'm not very familiar with Backbone so it's possible there's a blindly simple answer I'm just not aware of :D

Thanks again for your help.

 

Picture of Ben S
Re: Delaying course loading
by Ben S - Wednesday, 6 August 2014, 2:20 PM
 

I think the answer might be as simple as calling view.render() - but I'm not sure of how to do that from my model.

Edit: My current fix is to add the line

this.on('myPlugin:rerender', this.render);

to the initialise method of AdaptView (in adaptView.js), and then call myplugin.trigger('rerender'); once my plugin is finished. I understand using events is the 'backbone' way of doing things, but feels a bit hackish.

Picture of Gavin Nelson
Re: Delaying course loading
by Gavin Nelson - Wednesday, 6 August 2014, 3:20 PM
 

you could make your code more adapt-like by using adapts trigger and listen to methods

myplugin.trigger('rerender'); would become Adapt.trigger('myPlugin:rerender');

and this.on('myPlugin:rerender', this.render); would become this.listenTo(Adapt, 'myPlugin:rerender', this.render);

I dont think this affects how it runs but it will keep the events local to adapt. Also if your plugin will always fire this event, you might be able to take out the original call to render (if you haven't done so already) to avoid rendering the menu twice.