forked from h5p/moodle-mod_hvp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
xapi-collector.js
133 lines (120 loc) · 4.38 KB
/
xapi-collector.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* Collect results from xAPI events
*/
(function ($) {
/**
* Finds a H5P library instance in an array based on the content ID
*
* @param {Array} instances
* @param {number} contentId
* @returns {Object} Content instance
*/
function findInstanceInArray(instances, contentId) {
if (instances !== undefined && contentId !== undefined) {
for (var i = 0; i < instances.length; i++) {
if (instances[i].contentId === contentId) {
return instances[i];
}
}
}
}
/**
* Finds the global instance from content id by looking through the DOM
*
* @param {number} [contentId] Content identifier
* @returns {Object} Content instance
*/
function getH5PInstance(contentId) {
var iframes, instance = null; // Returning null means no instance is found.
// No content id given, search for instance.
if (!contentId) {
instance = H5P.instances[0];
if (!instance) {
iframes = document.getElementsByClassName('h5p-iframe');
// Assume first iframe.
instance = iframes[0].contentWindow.H5P.instances[0];
}
}
else {
// Try this documents instances.
instance = findInstanceInArray(H5P.instances, contentId);
if (!instance) {
// Locate iframes.
iframes = document.getElementsByClassName('h5p-iframe');
for (var i = 0; i < iframes.length; i++) {
// Search through each iframe for content.
instance = findInstanceInArray(iframes[i].contentWindow.H5P.instances, contentId);
if (instance) {
break;
}
}
}
}
return instance;
}
/**
* Get xAPI data for content type and send off.
*
* @param {number} contentId Content id
* @param {Object} event Original xAPI event
*/
function storeXAPIData(contentId, event) {
var xAPIData;
var instance = getH5PInstance(contentId);
// Use getXAPIData contract, needed to get children.
if (instance && instance.getXAPIData) {
xAPIData = instance.getXAPIData();
}
else {
// Fallback to event data.
xAPIData = {
statement: event.data.statement
};
}
// Ship the xAPI result.
$.post(H5PIntegration.ajax.xAPIResult, {
contentId: contentId,
xAPIResult: JSON.stringify(xAPIData)
}).done(function (data) {
if (data.error) {
console.debug('Storing xAPI results failed with error message:', data);
}
});
}
$(document).ready(function () {
// No external dispatcher.
if (!(window.H5P && H5P.externalDispatcher)) {
console.debug('External dispatcher not found');
return;
}
// No ajax path.
if (!(window.H5PIntegration && H5PIntegration.ajax && H5PIntegration.ajax.xAPIResult)) {
console.debug('No ajax path found');
return;
}
// Get emitted xAPI data.
H5P.externalDispatcher.on('xAPI', function (event) {
// Skip malformed events.
var hasStatement = event && event.data && event.data.statement;
if (!hasStatement) {
return;
}
var statement = event.data.statement;
var validVerb = statement.verb && statement.verb.display && statement.verb.display['en-US'];
if (!validVerb) {
return;
}
var isCompleted = statement.verb.display['en-US'] === 'answered' ||
statement.verb.display['en-US'] === 'completed';
var isChild = statement.context && statement.context.contextActivities &&
statement.context.contextActivities.parent &&
statement.context.contextActivities.parent[0] &&
statement.context.contextActivities.parent[0].id;
// Store only completed root events.
if (isCompleted && !isChild) {
// Get xAPI data with children if possible.
storeXAPIData(this.contentId, event);
}
});
});
})(H5P.jQuery);