MDL-28937 SCORM 2004 ADL TEST CM-01 MDL-28740 first part of check for hidecontinue...
[moodle.git] / mod / scorm / module.js
CommitLineData
5c2aa157
DM
1// This file is part of Moodle - http://moodle.org/
2//
3// Moodle is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// Moodle is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
15
16/**
17 * Javascript helper function for IMS Content Package module.
18 *
19 * @package mod-scorm
20 * @copyright 2009 Petr Skoda (http://skodak.org)
21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 */
23
22a79674
PH
24mod_scorm_next = null;
25mod_scorm_prev = null;
26mod_scorm_activate_item = null;
27
5c2aa157
DM
28M.mod_scorm = {};
29
fe3b9da3 30M.mod_scorm.init = function(Y, hide_nav, hide_toc, toc_title, window_name, launch_sco) {
99da7a95
DM
31 var scorm_disable_toc = false;
32 var scorm_hide_nav = true;
33 var scorm_hide_toc = true;
5c2aa157 34 if (hide_toc == 0) {
5f65d37c 35 scorm_hide_nav = false;
5c2aa157 36 scorm_hide_toc = false;
99da7a95
DM
37 } else if (hide_toc == 3) {
38 scorm_disable_toc = true;
5c2aa157
DM
39 }
40
41 var scorm_layout_widget;
42 var scorm_current_node;
43 var scorm_buttons = [];
44 var scorm_bloody_labelclick = false;
cac50377 45 var scorm_nav_panel;
5c2aa157 46
5c2aa157
DM
47 Y.use('yui2-resize', 'yui2-dragdrop', 'yui2-container', 'yui2-button', 'yui2-layout', 'yui2-treeview', 'yui2-json', 'yui2-event', function(Y) {
48
49 var scorm_activate_item = function(node) {
50 if (!node) {
51 return;
52 }
53 scorm_current_node = node;
54 scorm_current_node.highlight();
55
56 // remove any reference to the old API
57 if (window.API) {
58 window.API = null;
59 }
60 if (window.API_1484_11) {
61 window.API_1484_11 = null;
62 }
63 var url_prefix = M.cfg.wwwroot + '/mod/scorm/loadSCO.php?';
64 var el_old_api = document.getElementById('scormapi123');
65 if (el_old_api) {
66 el_old_api.parentNode.removeChild(el_old_api);
67 }
68
69 if (node.title) {
70 var el_scorm_api = document.getElementById("external-scormapi");
71 el_scorm_api.parentNode.removeChild(el_scorm_api);
72 el_scorm_api = document.createElement('script');
73 el_scorm_api.setAttribute('id','external-scormapi');
74 el_scorm_api.setAttribute('type','text/javascript');
75 var pel_scorm_api = document.getElementById('scormapi-parent');
76 pel_scorm_api.appendChild(el_scorm_api);
77 var api_url = M.cfg.wwwroot + '/mod/scorm/api.php?' + node.title;
78 document.getElementById('external-scormapi').src = api_url;
79 }
250821d5 80
5c2aa157
DM
81 var content = new YAHOO.util.Element('scorm_content');
82 try {
83 // first try IE way - it can not set name attribute later
84 // and also it has some restrictions on DOM access from object tag
85 if (window_name || node.title == null) {
86 var obj = document.createElement('<iframe id="scorm_object" src="">');
fe3b9da3
PH
87 if (window_name) {
88 var mine = window.open('','','width=1,height=1,left=0,top=0,scrollbars=no');
89 if(! mine) {
90 alert(M.str.scorm.popupsblocked);
91 }
92 mine.close()
93 }
5c2aa157
DM
94 }
95 else {
96 var obj = document.createElement('<iframe id="scorm_object" src="'+url_prefix + node.title+'">');
250821d5 97 }
6d67f349
PH
98 // fudge IE7 to redraw the screen
99 if (YAHOO.env.ua.ie > 5 && YAHOO.env.ua.ie < 8) {
100 obj.attachEvent("onload", scorm_resize_parent);
5c2aa157
DM
101 }
102 } catch (e) {
103 var obj = document.createElement('object');
104 obj.setAttribute('id', 'scorm_object');
105 obj.setAttribute('type', 'text/html');
106 if (!window_name && node.title != null) {
107 obj.setAttribute('data', url_prefix + node.title);
108 }
d1cf56e7
PH
109 if (window_name) {
110 var mine = window.open('','','width=1,height=1,left=0,top=0,scrollbars=no');
111 if(! mine) {
112 alert(M.str.scorm.popupsblocked);
fe3b9da3 113 }
d1cf56e7
PH
114 mine.close()
115 }
5c2aa157
DM
116 }
117 var old = YAHOO.util.Dom.get('scorm_object');
118 if (old) {
ca4eda13 119 if(window_name) {
d1cf56e7
PH
120 var cwidth = scormplayerdata.cwidth;
121 var cheight = scormplayerdata.cheight;
122 var poptions = scormplayerdata.popupoptions;
6d954dd3 123 scorm_openpopup(M.cfg.wwwroot + "/mod/scorm/loadSCO.php?" + node.title, window_name, poptions, cwidth, cheight);
ca4eda13
DM
124 } else {
125 content.replaceChild(obj, old);
d1cf56e7 126 }
5c2aa157
DM
127 } else {
128 content.appendChild(obj);
129 }
6d67f349 130
5c2aa157
DM
131 scorm_resize_frame();
132
a188aa49
PH
133 var left = scorm_layout_widget.getUnitByPosition('left');
134 if (left.expanded) {
135 scorm_current_node.focus();
136 }
5c2aa157
DM
137 if (scorm_hide_nav == false) {
138 scorm_fixnav();
139 }
140 };
141
22a79674
PH
142 mod_scorm_activate_item = scorm_activate_item;
143
5c2aa157
DM
144 /**
145 * Enables/disables navigation buttons as needed.
146 * @return void
147 */
148 var scorm_fixnav = function() {
6917eee8
DM
149 scorm_buttons[0].set('disabled', (scorm_skipprev(scorm_current_node) == null || scorm_skipprev(scorm_current_node).title == null));
150 scorm_buttons[1].set('disabled', (scorm_prev(scorm_current_node) == null || scorm_prev(scorm_current_node).title == null));
151 scorm_buttons[2].set('disabled', (scorm_up(scorm_current_node) == null) || scorm_up(scorm_current_node).title == null);
152 scorm_buttons[3].set('disabled', (scorm_next(scorm_current_node) == null) || scorm_next(scorm_current_node).title == null);
153 scorm_buttons[4].set('disabled', (scorm_skipnext(scorm_current_node) == null || scorm_skipnext(scorm_current_node).title == null));
5c2aa157
DM
154 };
155
6d67f349
PH
156 var scorm_resize_parent = function() {
157 // fudge IE7 to redraw the screen
158 parent.resizeBy(-10, -10);
159 parent.resizeBy(10, 10);
160 var ifr = YAHOO.util.Dom.get('scorm_object');
161 if (ifr) {
162 ifr.detachEvent("onload", scorm_resize_parent);
163 }
250821d5 164 };
5c2aa157
DM
165
166 var scorm_resize_layout = function(alsowidth) {
167 if (window_name) {
5c2aa157
DM
168 return;
169 }
170
171 if (alsowidth) {
5c2aa157
DM
172 scorm_layout_widget.setStyle('width', '');
173 var newwidth = scorm_get_htmlelement_size('content', 'width');
5c2aa157
DM
174 }
175 // make sure that the max width of the TOC doesn't go to far
6d67f349 176
5c2aa157
DM
177 var left = scorm_layout_widget.getUnitByPosition('left');
178 var maxwidth = parseInt(YAHOO.util.Dom.getStyle('scorm_layout', 'width'));
179 left.set('maxWidth', (maxwidth - 10));
180 var cwidth = left.get('width');
181 if (cwidth > (maxwidth - 10)) {
182 left.set('width', (maxwidth - 10));
183 }
184
ef297a21 185 scorm_layout_widget.setStyle('height', '100%');
9597f85d
PH
186 var center = scorm_layout_widget.getUnitByPosition('center');
187 center.setStyle('height', '100%');
188
189 // calculate the rough new height
190 newheight = YAHOO.util.Dom.getViewportHeight() *.82;
191 if (newheight < 600) {
192 newheight = 600;
193 }
194 scorm_layout_widget.set('height', newheight);
195
5c2aa157
DM
196 scorm_layout_widget.render();
197 scorm_resize_frame();
198
cac50377
PH
199 if (scorm_nav_panel) {
200 scorm_nav_panel.align('bl', 'bl');
201 }
5c2aa157
DM
202 };
203
204 var scorm_get_htmlelement_size = function(el, prop) {
205 var val = YAHOO.util.Dom.getStyle(el, prop);
206 if (val == 'auto') {
207 if (el.get) {
208 el = el.get('element'); // get real HTMLElement from YUI element
209 }
210 val = YAHOO.util.Dom.getComputedStyle(YAHOO.util.Dom.get(el), prop);
211 }
212 return parseInt(val);
213 };
214
215 var scorm_resize_frame = function() {
216 var obj = YAHOO.util.Dom.get('scorm_object');
217 if (obj) {
218 var content = scorm_layout_widget.getUnitByPosition('center').get('wrap');
219 // basically trap IE6 and 7
220 if (YAHOO.env.ua.ie > 5 && YAHOO.env.ua.ie < 8) {
221 if( obj.style.setAttribute ) {
222 obj.style.setAttribute("cssText", 'width: ' +(content.offsetWidth - 6)+'px; height: ' + (content.offsetHeight - 10)+'px;');
223 }
224 else {
225 obj.style.setAttribute('width', (content.offsetWidth - 6)+'px', 0);
226 obj.style.setAttribute('height', (content.offsetHeight - 10)+'px', 0);
227 }
228 }
229 else {
230 obj.style.width = (content.offsetWidth - 6)+'px';
231 obj.style.height = (content.offsetHeight - 10)+'px';
232 }
233 }
234 };
235
5c2aa157
DM
236 var scorm_up = function(node) {
237 var node = scorm_tree_node.getHighlightedNode();
238 if (node.depth > 0) {
239 return node.parent;
240 }
241 return null;
242 };
243
244 var scorm_lastchild = function(node) {
245 if (node.children.length) {
246 return scorm_lastchild(node.children[node.children.length-1]);
247 } else {
248 return node;
249 }
250 };
251
252 var scorm_prev = function(node) {
253 if (node.previousSibling && node.previousSibling.children.length) {
254 return scorm_lastchild(node.previousSibling);
255 }
256 return scorm_skipprev(node);
257 };
258
259 var scorm_skipprev = function(node) {
5c2aa157
DM
260 if (node.previousSibling) {
261 return node.previousSibling;
262 } else if (node.depth > 0) {
263 return node.parent;
264 }
265 return null;
266 };
267
268 var scorm_next = function(node) {
269 if (node === false) {
270 return scorm_tree_node.getRoot().children[0];
271 }
272 if (node.children.length) {
273 return node.children[0];
274 }
275 return scorm_skipnext(node);
276 };
277
278 var scorm_skipnext = function(node) {
5c2aa157
DM
279 if (node.nextSibling) {
280 return node.nextSibling;
281 } else if (node.depth > 0) {
282 return scorm_skipnext(node.parent);
283 }
284 return null;
285 };
286
22a79674
PH
287 mod_scorm_next = scorm_next;
288 mod_scorm_prev = scorm_prev;
289
5c2aa157
DM
290 // layout
291 YAHOO.widget.LayoutUnit.prototype.STR_COLLAPSE = M.str.moodle.hide;
292 YAHOO.widget.LayoutUnit.prototype.STR_EXPAND = M.str.moodle.show;
293
99da7a95
DM
294 if (scorm_disable_toc) {
295 scorm_layout_widget = new YAHOO.widget.Layout('scorm_layout', {
296 minWidth: 255,
297 minHeight: 600,
298 units: [
299 { position: 'left', body: 'scorm_toc', header: toc_title, width: 0, resize: true, gutter: '0px 0px 0px 0px', collapse: false},
300 { position: 'center', body: '<div id="scorm_content"></div>', gutter: '0px 0px 0px 0px', scroll: true}
301 ]
302 });
303 } else {
304 scorm_layout_widget = new YAHOO.widget.Layout('scorm_layout', {
305 minWidth: 255,
306 minHeight: 600,
307 units: [
308 { position: 'left', body: 'scorm_toc', header: toc_title, width: 250, resize: true, gutter: '2px 5px 5px 2px', collapse: true, minWidth:250, maxWidth: 590},
309 { position: 'center', body: '<div id="scorm_content"></div>', gutter: '2px 5px 5px 2px', scroll: true}
310 ]
311 });
312 }
313
5c2aa157
DM
314 scorm_layout_widget.render();
315 var left = scorm_layout_widget.getUnitByPosition('left');
99da7a95
DM
316 if (!scorm_disable_toc) {
317 left.on('collapse', function() {
318 scorm_resize_frame();
319 });
320 left.on('expand', function() {
321 scorm_resize_frame();
322 });
323 }
5c2aa157
DM
324 // ugly resizing hack that works around problems with resizing of iframes and objects
325 left._resize.on('startResize', function() {
326 var obj = YAHOO.util.Dom.get('scorm_object');
327 obj.style.display = 'none';
328 });
329 left._resize.on('endResize', function() {
330 var obj = YAHOO.util.Dom.get('scorm_object');
331 obj.style.display = 'block';
332 scorm_resize_frame();
333 });
334
335 // hide the TOC if that is the default
99da7a95
DM
336 if (!scorm_disable_toc) {
337 if (scorm_hide_toc == true) {
338 left.collapse();
339 }
5c2aa157 340 }
5c2aa157
DM
341 // TOC tree
342 var tree = new YAHOO.widget.TreeView('scorm_tree');
343 scorm_tree_node = tree;
344 tree.singleNodeHighlight = true;
345 tree.subscribe('labelClick', function(node) {
346 scorm_activate_item(node);
347 if (node.children.length) {
348 scorm_bloody_labelclick = true;
349 }
350 });
99da7a95
DM
351 if (!scorm_disable_toc) {
352 tree.subscribe('collapse', function(node) {
353 if (scorm_bloody_labelclick) {
354 scorm_bloody_labelclick = false;
355 return false;
356 }
357 });
358 tree.subscribe('expand', function(node) {
359 if (scorm_bloody_labelclick) {
360 scorm_bloody_labelclick = false;
361 return false;
362 }
363 });
364 }
5c2aa157
DM
365 tree.expandAll();
366 tree.render();
367
368 // navigation
369 if (scorm_hide_nav == false) {
cac50377 370 scorm_nav_panel = new YAHOO.widget.Panel('scorm_navpanel', { visible:true, draggable:true, close:false, xy: [250, 450],
5c2aa157 371 autofillheight: "body"} );
cac50377 372 scorm_nav_panel.setHeader(M.str.scorm.navigation);
250821d5 373
5c2aa157 374 //TODO: make some better&accessible buttons
cac50377
PH
375 scorm_nav_panel.setBody('<span id="scorm_nav"><button id="nav_skipprev">&lt;&lt;</button><button id="nav_prev">&lt;</button><button id="nav_up">^</button><button id="nav_next">&gt;</button><button id="nav_skipnext">&gt;&gt;</button></span>');
376 scorm_nav_panel.render();
5c2aa157
DM
377 scorm_buttons[0] = new YAHOO.widget.Button('nav_skipprev');
378 scorm_buttons[1] = new YAHOO.widget.Button('nav_prev');
379 scorm_buttons[2] = new YAHOO.widget.Button('nav_up');
380 scorm_buttons[3] = new YAHOO.widget.Button('nav_next');
381 scorm_buttons[4] = new YAHOO.widget.Button('nav_skipnext');
382 scorm_buttons[0].on('click', function(ev) {
383 scorm_activate_item(scorm_skipprev(scorm_tree_node.getHighlightedNode()));
384 });
385 scorm_buttons[1].on('click', function(ev) {
386 scorm_activate_item(scorm_prev(scorm_tree_node.getHighlightedNode()));
387 });
388 scorm_buttons[2].on('click', function(ev) {
389 scorm_activate_item(scorm_up(scorm_tree_node.getHighlightedNode()));
390 });
391 scorm_buttons[3].on('click', function(ev) {
392 scorm_activate_item(scorm_next(scorm_tree_node.getHighlightedNode()));
393 });
394 scorm_buttons[4].on('click', function(ev) {
395 scorm_activate_item(scorm_skipnext(scorm_tree_node.getHighlightedNode()));
396 });
cac50377 397 scorm_nav_panel.render();
5c2aa157
DM
398 }
399
400 // finally activate the chosen item
401 var scorm_first_url = tree.getRoot().children[0];
402 var nxt = false;
403 while (nxt = scorm_next(nxt)) {
404 if (nxt.title) {
405 expression = new RegExp('^.*?scoid=' + launch_sco + '.*?$');
406 matches = nxt.title.match(expression);
407 if (matches != null) {
408 scorm_first_url = nxt;
409 break;
410 }
411 }
412 }
413 scorm_activate_item(scorm_first_url);
414
415 // resizing
416 scorm_resize_layout(false);
417
418 // fix layout if window resized
419 window.onresize = function() {
420 scorm_resize_layout(true);
421 };
422 });
423};
22a79674
PH
424
425
426function scorm_get_prev() {
427 scorm_tree_node = YAHOO.widget.TreeView.getTree('scorm_tree');
428 if (scorm_tree_node) {
429 var hnode = scorm_tree_node.getHighlightedNode();
430 var prev = mod_scorm_prev(hnode);
431 if (prev) {
432 mod_scorm_activate_item(prev);
433 }
434 }
435}
436
437function scorm_get_next() {
438 scorm_tree_node = YAHOO.widget.TreeView.getTree('scorm_tree');
439 if (scorm_tree_node) {
440 var hnode = scorm_tree_node.getHighlightedNode();
441 var next = mod_scorm_next(hnode);
442 if (next) {
443 mod_scorm_activate_item(next);
444 }
445 }
446}