Commit | Line | Data |
---|---|---|
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 |
24 | mod_scorm_next = null; |
25 | mod_scorm_prev = null; | |
26 | mod_scorm_activate_item = null; | |
27 | ||
5c2aa157 DM |
28 | M.mod_scorm = {}; |
29 | ||
fe3b9da3 | 30 | M.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"><<</button><button id="nav_prev"><</button><button id="nav_up">^</button><button id="nav_next">></button><button id="nav_skipnext">>></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 | ||
426 | function 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 | ||
437 | function 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 | } |