Watch the video of this presentation: https://youtu.be/vevmhMXfiOU?t=1s
Learnosity is designed to support creative and powerful assessment building. So if you’ve ever looked on in envy or frustration at a competitor’s super-sleek assessment solution, then it’s time to rekindle your creative fire.
By quickly building professional-quality assessments using Learnosity’s tools, we’ll show how you can easily tailor every aspect of your assessment experience to make your end product just as polished, stylish and powerful as anything else on the market. But why make your assessments as good as what’s already out there when you can just as easily make them even better?
2. Michael Sharman
Director of Product & Engineering
michael.sharman@learnosity.com
Pierre Bergamin
Technical Lead - Assessment
pierre.bergamin@learnosity.com
Presenters
8. How to use our APIs <!-- HTML hook -->
<div id="learnosity_assess"></div>
<!-- Embed API script -->
<script src="https://items.learnosity.com"></script>
<script>
const initOptions = {
"security": {
// Security JSON
},
"request": {
// Initialization JSON
}
};
const itemsApp = LearnosityItems.init(initOptions, {
readyListener() {
},
errorListener() {
}
});
</script>
1. HTML hook
2. Embedding the API script
3. Initialization options
↳ server-side security signature
generation required
1. API initialization
9. Essential API hooks
App Instance
↳ Object containing methods to interact with
○ Public methods
○ Events
Ready Listener
↳ Function called when the API has initialised
Error Listener
↳ Function called when the errors are raised
const itemsApp = LearnosityItems.init(initOptions, {
readyListener() {
console.log(`API ready`);
},
errorListener(error) {
console.error(`an error occured`, error);
}
});
24. Customizing Learnosity styles
● Overriding Learnosity API styles
○ Questions or Assess APIs
○ CSS specificity
● We can host your custom stylesheets or you do it
29. ● Programmatically control
your assessment
● Get/Set data
● App instance
Public methods
// Example 1: Get the list of attempted items
const attemptedItems = itemsApp.attemptedItems();
/*
[
"ccore_ccs_rabbit",
"ccore_DropDowns_inline_cloze_mp4",
"ccore_sbalance_online_43081"
]
*/
// Example 2: Show a custom dialog
itemsApp.assessApp().dialogs().custom.show({
header: "My Custom Header",
body: "Custom body with <strong>html</strong> support",
buttons: [
{
button_id: "my_primary_button",
label: "My Primary Button",
is_primary: true
},
{
button_id: "my_standard_button",
label: "My Standard Button",
is_primary: false
}
]
});
// Dismiss the custom dialog
itemsApp.assessApp().dialogs().custom.hide();
30. Public methods
addAccessibilityPalettes eventsApp getItems hasStarted on setAccessibility
addItems feature getItemsMetadata item.checkImages once setHeight
append features getProgress item.retryLoadImages question start
attemptedItems getCurrentItem getQuestions item.flag questions submit
attemptedQuestions getFeatures getResponses items.goto questionsApp unsaveableQuestions
audioPlayer getItemPosition getScores items.previous reset validQuestions
dialogs.show getItemResponses getSubmitssionData items.next safeToUnload validatableQuestions
dialogs.hide getItemScores getTime off save And more to come!
34. Events
● Player events
● Questions events
.on('eventName', callback, ctx);
↳ Binds a callback function that will be invoked whenever
the eventName is triggered.
↳ To supply a context to execute the callback on, pass the
optional third argument.
.once('eventName', callback, ctx);
.off('eventName', callback, ctx);
Plug into the API event bus
/* Example 1 - player event */
// Event handler - log the index of the item we navigate to
// and save
function itemChangedHandler(itemIndex) {
console.log('itemChanged', itemIndex);
itemsApp.save();
}
itemsApp.assessApp().on('item:changed', itemChangedHandler);
/* Example 2 - question facade event */
const audioQuestion = myQuestionsApp.question('60001');
// Start recording
audioQuestion.recording.start();
// Play response when recording is stopped
audioQuestion.on('recording:stopped', () => {
audioQuestion.response.play();
});
35. Back to our “custom dialog” solution
assessApp.on('button:answer1_button:clicked', () => {
console.log('That is right, well done!');
const lastItemIndex = Object.keys(assessApp.getItems()).length - 1;
// Dismiss the custom dialog
assessApp.dialogs().custom.hide();
// Go to the last item
assessApp.items().goto(lastItemIndex);
});
assessApp.on('button:answer2_button:clicked', () => {
console.log('Sorry mate, you can start your test again!');
// Dismiss the custom dialog
assessApp.dialogs().custom.hide();
// Go to the first item
assessApp.items().goto(0);
});
const assessApp = itemsApp.assessApp();
assessApp.dialogs().custom.show({
header: "How many Question types does Learnosity offer?",
body: "You get a <B>special</b> prize if you get it right!",
buttons: [
{
button_id: "answer1_button",
label: "65 or more",
is_primary: true
},
{
button_id: "answer2_button",
label: "64 or less",
is_primary: true
}
]
});
41. Custom questions
Create your own Question Types to be used within Learnosity
Create JSON definition1
{
"response_id": "custom-response-1",
"type": "custom",
"js": "//mysite.com/demos/custom_shorttext.js",
...
}
2
LearnosityAmd.define(['underscore', 'mathcore'],
(_, mathcore) => {
/* Custom Question Class */
class Question {
constructor(options) { /* ... */ }
}
return { Question, /* ... */ };
});
Use Learnosity module definition
3 Scoring
isValid() { /* ... */ }
score() { /* ... */ }
maxScore() { /* ... */ }
42. Customization continuum
Configure Style Extend
Simplicity Simple Pretty Simple Simple if you know JavaScript
Frequency All customers Some customers A few customers
Skills/Tools Learnosity Learnosity + CSS Learnosity + JavaScript
Time Minutes to hours Hours to days Days to weeks
More Effort & Added ValueLess Effort
43. ● Learnosity is designed to be customized
● Customize only the areas that are important to your users
● Only limited by your imagination.
● Allows you to easily differentiate your product, while taking
advantage of cutting-edge, scalable, powerful solutions.
Conclusions
what we’re going to talk about
- Basic setup - getting started
- Configuration. - changing settings
- Styling - bring it all together
- Customisation. - adding code and public methods
Before we start going deeper into customizing assessment, let’s have a quick reminder of some Learnosity 101s
Learnosity APIs are using common the open web technologies that are HTML5/JavaScript and CSS.
It means that our APIs can be embedded in any of your HTML pages.
Before we go deeper in details on how to customize Learnosity APIs, let’s have a look at the basics on how to run one of our API into your page:
The first thing you need to do is to include an API hook into your page. These hooks are HTML elements where the API will render.
You will then need to embed the API script in your page using a HTML <script> tag
The next step is to have your initialization options in the page. This can be a JavaScript Object or a JSON. It will contain the API configuration that you want to load and the security package.
You will need to generate the signature on the server side to keep your consumer key and secret safe. We provide SDKs in various languages to do that.
Once you have all that, the last thing you need to do is to call our init public method with the initi options as parameter and also another object that contains methods
The ready listener is a method called when the api has finished initializing
that will be called when the API is ready or when an error occurs.
The itemsApp object is the instance of your API that you will need to use to call public methods.
As michael said, the approach that we had was allowing people to turn on and off some UI elements but didn’t allow them to position them inside the player.
To solve this issue, we decided to split the player in areas that we called regions.
We have the items regions, which is where the items will be rendered, bottom regions, a right menu where you can place the table of content and a slide in/out menu, and top regions where you can place title, timer, etc.
You can basically move these around as you wish.
We identified 3 very commonly used configurations and made presets to make your life easier (you don’t need to build a full JSON)
The first one is “MAIN” and delivers the configuration that you can see on the left here.
Describe regions
Descript items height behaviour
The second preset we built is essentially the same as the “main” one but offers more width for the items container by moving the pager to the bottom. This will better fit some mobile devices.
The items container behaves the same as “main”.
The last preset we built is “horizontal-fixed”. The elements are again the same as “main” and “horizontal” but we have a different behavior for the items container.
Instead of the player resize to fit the full height of each item, we now have a scrollbar for long items.
The player height will also resize to fit 100% of the viewport height.
This preset is great for you if you want to have the player use as much space of your application as it can and have a distraction free assessment.
What if you want more flexibility?
You can control where elements go, set the order, etc. by passing a “regions” JSON object.
Each region is an Array in which you can order elements in.
It allows you to have very rich test experiences or minimalistic UIs.
…
A great tool that Learnosity APIs offer to extend your solution is public methods
Public methods allow you to programmatically control your assessment (the player or individual questions).
You can get and set data.
What if you want to use Learnosity Assess player with your own previous and next buttons?
NM
These are business decisions - as to how important is it for your project.