scorm_api.php 91 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use ChamiloSession as Session;
  4. /**
  5. * API event handler functions for Scorm 1.1 and 1.2 and 1.3 (latter not fully supported)
  6. * This script is divided into three sections.
  7. * The first section (below) is the initialisation part.
  8. * The second section is the SCORM object part
  9. * The third section defines the event handlers for Chamilo's internal messaging
  10. * and frames refresh.
  11. *
  12. * @author Denes Nagy <darkden@freemail.hu> (original author - 2003-2004)
  13. * @author Yannick Warnier <ywarnier@beeznest.org> (extended and maintained - 2005-2014)
  14. *
  15. * @version v 1.2
  16. *
  17. * @package chamilo.learnpath.scorm
  18. */
  19. // If you open the imsmanifest.xml via local machine (f.ex.: file://c:/...), then the Apiwrapper.js
  20. // of Maritime Navigation when trying to execute this row
  21. // var result = api.LMSInitialize("");
  22. // get the error response : you are not authorized to call this function
  23. // Flag to allow for anonymous user - needs to be set before global.inc.php.
  24. $use_anonymous = true;
  25. require_once __DIR__.'/../inc/global.inc.php';
  26. $file = Session::read('file');
  27. /** @var learnpath $oLP */
  28. $oLP = UnserializeApi::unserialize(
  29. 'lp',
  30. Session::read('lpobject')
  31. );
  32. /** @var learnpathItem $oItem */
  33. $oItem = isset($oLP->items[$oLP->current]) ? $oLP->items[$oLP->current] : null;
  34. if (!is_object($oItem)) {
  35. error_log('New LP - scorm_api - Could not load oItem item', 0);
  36. exit;
  37. }
  38. $autocomplete_when_80pct = 0;
  39. $user = api_get_user_info();
  40. $userId = api_get_user_id();
  41. header('Content-type: text/javascript');
  42. ?>var scorm_logs=<?php echo (empty($oLP->scorm_debug) or (!api_is_course_admin() && !api_is_platform_admin())) ? '0' : '3'; ?>; //debug log level for SCORM. 0 = none, 1=light, 2=a lot, 3=all - displays logs in log frame
  43. var lms_logs = 0; //debug log level for LMS actions. 0=none, 1=light, 2=a lot, 3=all
  44. // API Object initialization (eases access later on)
  45. function APIobject() {
  46. this.LMSInitialize=LMSInitialize; //for Scorm 1.2
  47. this.Initialize=LMSInitialize; //for Scorm 1.3
  48. this.LMSGetValue=LMSGetValue;
  49. this.GetValue=LMSGetValue;
  50. this.LMSSetValue=LMSSetValue;
  51. this.SetValue=LMSSetValue;
  52. this.LMSCommit=LMSCommit;
  53. this.Commit=LMSCommit;
  54. this.LMSFinish=LMSFinish;
  55. this.Finish=LMSFinish;
  56. this.LMSGetLastError=LMSGetLastError;
  57. this.GetLastError=LMSGetLastError;
  58. this.LMSGetErrorString=LMSGetErrorString;
  59. this.GetErrorString=LMSGetErrorString;
  60. this.LMSGetDiagnostic=LMSGetDiagnostic;
  61. this.GetDiagnostic=LMSGetDiagnostic;
  62. this.Terminate=Terminate; //only in Scorm 1.3
  63. this.save_asset = lms_save_asset;
  64. this.void_save_asset = chamilo_void_save_asset;
  65. }
  66. // it is not sure that the scos use the above declarations. The following
  67. // multiple declarations are to make sure we have an API object for each type of
  68. // SCORM
  69. var API = new APIobject(); //for scorm 1.2
  70. var api = API;
  71. //var API_1484_11 = new APIobject(); //for scorm 1.3
  72. //var api_1484_11 = API_1484_11;
  73. // SCORM-specific Error codes
  74. var G_NoError = 0;
  75. var G_GeneralException = 101;
  76. var G_ServerBusy = 102; // this is not in the Scorm1.2_Runtime document
  77. var G_InvalidArgumentError = 201;
  78. var G_ElementCannotHaveChildren = 202;
  79. var G_ElementIsNotAnArray = 203;
  80. var G_NotInitialized = 301;
  81. var G_NotImplementedError = 401;
  82. var G_InvalidSetValue = 402;
  83. var G_ElementIsReadOnly = 403;
  84. var G_ElementIsWriteOnly = 404;
  85. var G_IncorrectDataType = 405;
  86. // SCORM-specific Error messages
  87. var G_NoErrorMessage = '';
  88. var G_GeneralExceptionMessage = 'General Exception';
  89. var G_ServerBusyMessage = 'Server busy'; // this is not in the Scorm1.2_Runtime document
  90. var G_InvalidArgumentErrorMessage = 'Invalid argument error';
  91. var G_ElementCannotHaveChildrenMessage = 'Element cannot have children';
  92. var G_ElementIsNotAnArrayMessage = 'Element not an array. Cannot have count';
  93. var G_NotInitializedMessage = 'Not initialized';
  94. var G_NotImplementedErrorMessage = 'Not implemented error';
  95. var G_InvalidSetValueMessage = 'Invalid set value, element is a keyword';
  96. var G_ElementIsReadOnlyMessage = 'Element is read only';
  97. var G_ElementIsWriteOnlyMessage = 'Element is write only';
  98. var G_IncorrectDataTypeMessage = 'Incorrect Data Type';
  99. var olms = new Object();
  100. //the last recorded error message was:
  101. olms.G_LastError = G_NoError ;
  102. olms.G_LastErrorMessage = 'No error';
  103. //this is not necessary and is only provided to make bad Articulate contents
  104. // shut up (and not trigger useless JS messages)
  105. olms.G_LastErrorString = 'No error';
  106. //these variables are provided for better control of the current status in the
  107. // SCORM exchange
  108. olms.commit = false;
  109. // informative array helping to select variables to save, later on
  110. olms.scorm_variables = new Array(
  111. 'cmi.core.score.raw',
  112. 'cmi.core.score.max',
  113. 'cmi.core.score.min',
  114. 'cmi.core.lesson_location',
  115. 'cmi.core.lesson_status',
  116. 'cmi.completion_status',
  117. 'cmi.core.session_time',
  118. 'cmi.score.scaled',
  119. 'cmi.success_status',
  120. 'cmi.suspend_data',
  121. 'cmi.core.exit',
  122. 'interactions'
  123. );
  124. // manage variables to save or not
  125. olms.variable_to_send = new Array();
  126. // temporary list of variables (gets set to true when set through LMSSetValue)
  127. olms.updatable_vars_list = new Array();
  128. // marker of whether the LMSFinish() function was called, which is important for SCORM behaviour
  129. olms.finishSignalReceived = 0;
  130. // marker to remember if the SCO has calles a "set" on lesson_status
  131. olms.statusSignalReceived = 0;
  132. // Strictly scorm variables
  133. olms.score=<?php echo $oItem->get_score(); ?>;
  134. olms.max='<?php echo $oItem->get_max(); ?>';
  135. olms.min='<?php echo $oItem->get_min(); ?>';
  136. olms.lesson_status='<?php echo $oItem->get_status(); ?>';
  137. olms.session_time='<?php echo $oItem->get_scorm_time('js'); ?>';
  138. olms.suspend_data = '<?php echo $oItem->get_suspend_data(); ?>';
  139. olms.lesson_location = '<?php echo $oItem->get_lesson_location(); ?>';
  140. olms.total_time = '<?php echo $oItem->get_scorm_time('js'); ?>';
  141. olms.mastery_score = '<?php echo $oItem->get_mastery_score(); ?>';
  142. olms.launch_data = '<?php echo $oItem->get_launch_data(); ?>';
  143. olms.max_time_allowed = '<?php echo $oItem->get_max_time_allowed(); ?>';
  144. olms.interactions = new Array(<?php echo $oItem->get_interactions_js_array(); ?>);
  145. olms.item_objectives = new Array();
  146. olms.info_lms_item = new Array();
  147. // Chamilo internal variables (not SCORM)
  148. // olms.saved_lesson_status = 'not attempted';
  149. olms.lms_lp_id = <?php echo $oLP->get_id(); ?>;
  150. olms.lms_item_id = <?php echo $oItem->get_id(); ?>;
  151. olms.lms_initialized = 0;
  152. // switch_finished indicates if the switch process is finished (if it has gone
  153. // through LMSInitialize() for the new item. Until then, all LMSSetValue()
  154. // commands received are executed on the *previous/current* item
  155. // This flag is updated in LMSInitialize() and in switch_item()
  156. olms.switch_finished = 0;
  157. //olms.lms_total_lessons = <?php echo $oLP->get_total_items_count(); ?>;
  158. //olms.lms_complete_lessons = <?php echo $oLP->get_complete_items_count(); ?>;
  159. //olms.lms_progress_bar_mode = '<?php echo $oLP->progress_bar_mode; ?>';
  160. //if(lms_progress_bar_mode == ''){lms_progress_bar_mode='%';}
  161. olms.lms_view_id = '<?php echo $oLP->get_view(); ?>';
  162. if(olms.lms_view_id == ''){ olms.lms_view_id = 1;}
  163. olms.lms_user_id = '<?php echo $userId; ?>';
  164. olms.lms_next_item = '<?php echo $oLP->get_next_item_id(); ?>';
  165. olms.lms_previous_item = '<?php echo $oLP->get_previous_item_id(); ?>';
  166. olms.lms_lp_type = '<?php echo $oLP->get_type(); ?>';
  167. olms.lms_item_type = '<?php echo $oItem->get_type(); ?>';
  168. olms.lms_item_credit = '<?php echo $oItem->get_credit(); ?>';
  169. olms.lms_item_lesson_mode = '<?php echo $oItem->get_lesson_mode(); ?>';
  170. olms.lms_item_launch_data = '<?php echo addslashes($oItem->get_launch_data()); ?>';
  171. olms.lms_item_core_exit = '<?php echo $oItem->get_core_exit(); ?>';
  172. olms.lms_course_id = '<?php echo $oLP->get_course_int_id(); ?>';
  173. olms.lms_session_id = '<?php echo api_get_session_id(); ?>';
  174. olms.lms_course_code = '<?php echo $oLP->getCourseCode(); ?>';
  175. olms.lms_course_id = '<?php echo $oLP->get_course_int_id(); ?>';
  176. <?php echo $oLP->get_items_details_as_js('olms.lms_item_types'); ?>
  177. // Following definition of cmi.core.score.raw in SCORM 1.2, "LMS should
  178. // initialize this to an empty string ("") upon initial launch of a SCO. The
  179. // SCO is responsible for setting this value. If an LMSGetValue() is requested
  180. // before the SCO has set this value, then the LMS should return an empty
  181. // string ("")
  182. // As Chamilo initializes this to 0 for non-sco, we need a little hack here.
  183. if (olms.score == 0 && olms.lms_item_type == 'sco' && olms.lesson_status == 'not attempted') {
  184. olms.score = "";
  185. }
  186. olms.asset_timer = 0;
  187. olms.userfname = '<?php echo str_replace("'", "\\'", $user['firstname']); ?>';
  188. olms.userlname = '<?php echo str_replace("'", "\\'", $user['lastname']); ?>';
  189. olms.execute_stats = false;
  190. var courseUrl = '?cidReq='+olms.lms_course_code+'&id_session='+olms.lms_session_id;
  191. /**
  192. * Add the "addListeners" function to the "onload" event of the window and
  193. * start the timer if necessary (asset)
  194. */
  195. addEvent(window, 'load', addListeners, false);
  196. // Initialize stuff when the page is loaded
  197. $(function() {
  198. logit_lms('document.ready event starts');
  199. logit_lms('These logs are generated by the main/lp/scorm_api.php JS '
  200. + 'library when the admin has clicked on the debug icon in the '
  201. + 'learning paths list: '
  202. + 'lines prefixed with "LMS:" refer to actions taken on the LMS side, '
  203. + 'while lines prefixed with "SCORM:" refer to actions taken to match '
  204. + 'the SCORM standard at the JS level.', 3);
  205. logit_scorm('LMSSetValue calls are shown in red for better visibility.', 0);
  206. logit_scorm('Other SCORM calls are shown in orange.', 1);
  207. logit_lms('To add new messages to these logs, use logit_lms() or logit_scorm().');
  208. olms.info_lms_item[0] = '<?php echo $oItem->get_id(); ?>';
  209. olms.info_lms_item[1] = '<?php echo $oItem->get_id(); ?>';
  210. $("#content_id").load(function() {
  211. logit_lms('#content_id load event starts');
  212. olms.info_lms_item[0] = olms.info_lms_item[1];
  213. // Only trigger the LMSInitialize automatically if not SCO
  214. if (olms.lms_item_types['i'+olms.info_lms_item[1]] != 'sco') {
  215. LMSInitialize();
  216. } else {
  217. logit_lms('Content type is SCO and is responsible to launch LMSInitialize() on its own - Skipping',2);
  218. }
  219. });
  220. });
  221. // This code was moved inside LMSInitialize()
  222. if (olms.lms_lp_type == 1 || olms.lms_item_type == 'asset' || olms.lms_item_type == 'document') {
  223. xajax_start_timer();
  224. }
  225. /**
  226. * The following section represents a set of mandatory functions for SCORM
  227. */
  228. /**
  229. * Function called mandatorily by the SCORM content to start the SCORM comm
  230. * This is the initialize function of all APIobjects
  231. * @return string 'true' or 'false'. Returning a string is mandatory (SCORM).
  232. */
  233. function LMSInitialize() {
  234. /* load info for this new item by calling the js_api_refresh command in
  235. * the message frame. The message frame will update the JS variables by
  236. * itself, in JS, by doing things like top.lesson_status = 'not attempted'
  237. * and that kind of stuff, so when the content loads in the content frame
  238. * it will have all the correct variables set
  239. */
  240. logit_scorm('LMSInitialize()');
  241. olms.G_LastError = G_NoError ;
  242. olms.G_LastErrorMessage = 'No error';
  243. olms.lms_initialized = 0;
  244. olms.finishSignalReceived = 0;
  245. olms.statusSignalReceived = 0;
  246. olms.switch_finished = 0;
  247. // if there are more parameters than ""
  248. if (arguments.length > 1) {
  249. olms.G_LastError = G_InvalidArgumentError;
  250. olms.G_LastErrorMessage = G_InvalidArgumentErrorMessage;
  251. logit_scorm('Error '+ G_InvalidArgumentError + G_InvalidArgumentErrorMessage, 0);
  252. return('false');
  253. } else {
  254. //reinit the list of modified variables
  255. reinit_updatable_vars_list();
  256. // Get LMS values for this item
  257. var params = {
  258. 'lid': olms.lms_lp_id,
  259. 'uid': olms.lms_user_id,
  260. 'vid': olms.lms_view_id,
  261. 'iid': olms.lms_item_id
  262. };
  263. $.ajax({
  264. type: "POST",
  265. url: "lp_ajax_initialize.php" + courseUrl,
  266. data: params,
  267. dataType: 'script',
  268. async: false,
  269. success:function(data) {
  270. $('video:not(.skip), audio:not(.skip)').mediaelementplayer();
  271. }
  272. });
  273. olms.lms_initialized = 1;
  274. olms.switch_finished = 1;
  275. // log a more complete object dump when initializing, so we know what data hasn't been cleaned
  276. var log = '\nitem : '+ olms.lms_item_id
  277. + '\nitem_type : '+ olms.lms_item_type
  278. + '\nscore : '+ olms.score
  279. + '\nmax : '+ olms.max
  280. + '\nmin : '+ olms.min
  281. + '\nlesson_status : '+ olms.lesson_status
  282. + '\nsession_time : '+ olms.session_time
  283. + '\nlesson_location : '+ olms.lesson_location
  284. + '\nsuspend_data : '+ olms.suspend_data
  285. + '\ntotal_time : '+ olms.total_time
  286. + '\nmastery_score : '+ olms.mastery_score
  287. + '\nmax_time_allowed: '+ olms.max_time_allowed
  288. + '\ncredit : '+ olms.lms_item_credit
  289. + '\nlms_lp_id : '+ olms.lms_lp_id
  290. + '\nlms_user_id : '+ olms.lms_user_id
  291. + '\nlms_view_id : '+ olms.lms_view_id
  292. + '\nfinishSignalReceived : '+ olms.finishSignalReceived
  293. + '\nstatusSignalReceived : '+ olms.statusSignalReceived
  294. ;
  295. logit_scorm('LMSInitialize() with params: '+log);
  296. if(olms.lms_item_type == 'sco'){
  297. $("#tab-iframe").removeClass();
  298. $("#tab-iframe").addClass("tab-content iframe_"+olms.lms_item_type);
  299. }
  300. if (olms.lms_lp_type == 1 || olms.lms_item_type == 'asset' || olms.lms_item_type == 'document') {
  301. xajax_start_timer();
  302. }
  303. if (olms.lms_item_type == 'quiz') {
  304. update_toc(olms.lesson_status, olms.lms_item_id);
  305. }
  306. <?php
  307. $glossaryExtraTools = api_get_setting('show_glossary_in_extra_tools');
  308. $fixLinkSetting = api_get_configuration_value('lp_fix_embed_content');
  309. $showGlossary = in_array($glossaryExtraTools, ['true', 'lp', 'exercise_and_lp']);
  310. if ($showGlossary) {
  311. if (api_get_setting('show_glossary_in_documents') == 'ismanual') {
  312. ?>
  313. if (olms.lms_item_type == 'sco') {
  314. attach_glossary_into_scorm('automatic');
  315. } else {
  316. attach_glossary_into_scorm('manual');
  317. }
  318. <?php
  319. } elseif (api_get_setting('show_glossary_in_documents') == 'isautomatic') {
  320. ?>
  321. attach_glossary_into_scorm('automatic');
  322. <?php
  323. } ?>
  324. <?php
  325. } ?>
  326. <?php if ($fixLinkSetting) {
  327. ?>
  328. attach_glossary_into_scorm('fix_links');
  329. <?php
  330. } ?>
  331. return('true');
  332. }
  333. }
  334. /**
  335. * Twin sister of LMSInitialize(). Only provided for backwards compatibility.
  336. * this is the initialize function of all APIobjects
  337. */
  338. function Initialize() {
  339. return LMSInitialize();
  340. }
  341. /**
  342. * Gets a value in the current SCORM context and returns it to the calling SCO
  343. * @param string The name of the value we want
  344. * @return string All return values must be string (see SCORM)
  345. */
  346. function LMSGetValue(param) {
  347. olms.G_LastError = G_NoError;
  348. olms.G_LastErrorMessage = 'No error';
  349. var result = '';
  350. // the LMSInitialize is missing
  351. if (olms.lms_initialized == 0) {
  352. if (param == 'cmi.core.score.raw') {
  353. return '';
  354. }
  355. olms.G_LastError = G_NotInitialized;
  356. olms.G_LastErrorMessage = G_NotInitializedMessage;
  357. logit_scorm('LMSGetValue('+param+') on item id '+olms.lms_item_id+':<br />=> Error '+ G_NotInitialized + ' ' +G_NotInitializedMessage, 0);
  358. return '';
  359. }
  360. // Chamilo does not support these SCO object properties
  361. if (param == 'cmi.student_preference.text' ||
  362. param == 'cmi.student_preference.language' ||
  363. param == 'cmi.student_preference.speed' ||
  364. param == 'cmi.student_preference.audio' ||
  365. param == 'cmi.student_preference._children' ||
  366. param == 'cmi.student_data.time_limit_action' ||
  367. param == 'cmi.comments' ||
  368. param == 'cmi.comments_from_lms' ||
  369. /* The following properties were part of SCORM 1.0 or never implemented at all
  370. but seem to react badly to Captivate content producer when not defined */
  371. param == 'cmi.student_demographics._children' ||
  372. param == 'cmi.student_demographics.city' ||
  373. param == 'cmi.student_demographics.class' ||
  374. param == 'cmi.student_demographics.company' ||
  375. param == 'cmi.student_demographics.country' ||
  376. param == 'cmi.student_demographics.experience' ||
  377. param == 'cmi.student_demographics.familiar_name' ||
  378. param == 'cmi.student_demographics.instructor_name' ||
  379. param == 'cmi.student_demographics.title' ||
  380. param == 'cmi.student_demographics.native_language' ||
  381. param == 'cmi.student_demographics.state' ||
  382. param == 'cmi.student_demographics.street_address' ||
  383. param == 'cmi.student_demographics.telephone' ||
  384. param == 'cmi.student_demographics.years_experience' ) {
  385. // the value is not supported
  386. olms.G_LastError = G_NotImplementedError ;
  387. olms.G_LastErrorString = G_NotImplementedErrorMessage;
  388. logit_scorm("LMSGetValue ('"+param+"') Error '"+G_NotImplementedErrorMessage+"'",1);
  389. result = '';
  390. return result;
  391. }
  392. if (param=='cmi.student_demographics.first_name') {
  393. result=olms.userfname;
  394. } else if(param=='cmi.student_demographics.last_name') {
  395. result=olms.userlname;
  396. // ---- cmi.core._children
  397. } else if(param=='cmi.core._children' || param=='cmi.core_children'){
  398. result='entry, exit, lesson_status, student_id, student_name, lesson_location, total_time, credit, lesson_mode, score, session_time';
  399. } else if(param == 'cmi.core.entry'){
  400. // ---- cmi.core.entry
  401. if(olms.lms_item_core_exit=='none') {
  402. result='ab-initio';
  403. } else if(olms.lms_item_core_exit=='suspend') {
  404. result='resume';
  405. } else {
  406. result='';
  407. }
  408. } else if(param == 'cmi.core.exit') {
  409. // ---- cmi.core.exit
  410. result='';
  411. olms.G_LastError = G_ElementIsWriteOnly;
  412. } else if(param == 'cmi.core.session_time'){
  413. result='';
  414. olms.G_LastError = G_ElementIsWriteOnly;
  415. } else if(param == 'cmi.core.lesson_status'){
  416. // ---- cmi.core.lesson_status
  417. if (olms.lesson_status != '') {
  418. result = olms.lesson_status;
  419. } else {
  420. //result='not attempted';
  421. }
  422. } else if(param == 'cmi.core.student_id'){
  423. // ---- cmi.core.student_id
  424. result='<?php echo $userId; ?>';
  425. } else if(param == 'cmi.core.student_name'){
  426. // ---- cmi.core.student_name
  427. <?php
  428. $who = addslashes($user['lastname']).', '.addslashes($user['firstname']);
  429. echo "result='$who';";
  430. ?>
  431. } else if(param == 'cmi.core.lesson_location'){
  432. // ---- cmi.core.lesson_location
  433. result=olms.lesson_location;
  434. } else if(param == 'cmi.core.total_time'){
  435. // ---- cmi.core.total_time
  436. result=olms.total_time;
  437. } else if(param == 'cmi.core.score._children'){
  438. // ---- cmi.core.score._children
  439. result='raw,min,max';
  440. } else if(param == 'cmi.core.score.raw'){
  441. // ---- cmi.core.score.raw
  442. result=olms.score;
  443. } else if(param == 'cmi.core.score.max'){
  444. // ---- cmi.core.score.max
  445. result=olms.max;
  446. } else if(param == 'cmi.core.score.min'){
  447. // ---- cmi.core.score.min
  448. result=olms.min;
  449. } else if(param == 'cmi.core.score'){
  450. // ---- cmi.core.score -- non-standard item, provided as cmi.core.score.raw just in case
  451. result=olms.score;
  452. } else if(param == 'cmi.core.credit'){
  453. // ---- cmi.core.credit
  454. result = olms.lms_item_credit;
  455. } else if(param == 'cmi.core.lesson_mode'){
  456. // ---- cmi.core.lesson_mode
  457. result = olms.lms_item_lesson_mode;
  458. } else if(param == 'cmi.suspend_data'){
  459. // ---- cmi.suspend_data
  460. result = olms.suspend_data;
  461. } else if(param == 'cmi.launch_data'){
  462. // ---- cmi.launch_data
  463. result = olms.lms_item_launch_data;
  464. } else if(param == 'cmi.objectives._children'){
  465. // ---- cmi.objectives._children
  466. result = 'id,score,status';
  467. } else if(param == 'cmi.objectives._count'){
  468. // ---- cmi.objectives._count
  469. //result='<?php echo $oItem->get_view_count(); ?>';
  470. result = olms.item_objectives.length;
  471. } else if(param.substring(0,15)== 'cmi.objectives.'){
  472. var myres = '';
  473. if(myres = param.match(/cmi.objectives.(\d+).(id|score|status|_children)(.*)/)) {
  474. var obj_id = myres[1];
  475. var req_type = myres[2];
  476. if(olms.item_objectives[obj_id]==null) {
  477. if(req_type == 'id') {
  478. result = '';
  479. } else if(req_type == '_children'){
  480. result = 'id,score,status';
  481. } else if(req_type == 'score'){
  482. if(myres[3]==null) {
  483. result = '';
  484. olms.G_LastError = G_NotImplementedError;
  485. olms.G_LastErrorString = 'Not implemented yet';
  486. }else if (myres[3] == '._children'){
  487. result = 'raw,min,max'; //non-standard, added for NetG
  488. }else if (myres[3] == '.raw'){
  489. result = '';
  490. }else if (myres[3] == '.max'){
  491. result = '';
  492. }else if (myres[3] == '.min'){
  493. result = '';
  494. }else{
  495. result = '';
  496. olms.G_LastError = G_NotImplementedError;
  497. olms.G_LastErrorString = 'Not implemented yet';
  498. }
  499. } else if(req_type == 'status'){
  500. result = 'not attempted';
  501. }
  502. } else {
  503. //the object is not null
  504. if(req_type == 'id') {
  505. result = olms.item_objectives[obj_id][0];
  506. } else if(req_type == '_children'){
  507. result = 'id,score,status';
  508. } else if(req_type == 'score'){
  509. if(myres[3]==null) {
  510. result = '';
  511. olms.G_LastError = G_NotImplementedError;
  512. olms.G_LastErrorString = 'Not implemented yet';
  513. } else if (myres[3] == '._children'){
  514. result = 'raw,min,max'; //non-standard, added for NetG
  515. } else if (myres[3] == '.raw'){
  516. if(olms.item_objectives[obj_id][2] != null)
  517. {
  518. result = olms.item_objectives[obj_id][2];
  519. }else{
  520. result = '';
  521. }
  522. } else if (myres[3] == '.max'){
  523. if(olms.item_objectives[obj_id][3] != null) {
  524. result = olms.item_objectives[obj_id][3];
  525. }else{
  526. result = '';
  527. }
  528. } else if (myres[3] == '.min') {
  529. if(olms.item_objectives[obj_id][4] != null) {
  530. result = olms.item_objectives[obj_id][4];
  531. } else {
  532. result = '';
  533. }
  534. } else{
  535. result = '';
  536. olms.G_LastError = G_NotImplementedError;
  537. olms.G_LastErrorString = 'Not implemented yet';
  538. }
  539. } else if(req_type == 'status'){
  540. if(olms.item_objectives[obj_id][1] != null) {
  541. result = olms.item_objectives[obj_id][1];
  542. } else {
  543. result = 'not attempted';
  544. }
  545. }
  546. }
  547. }
  548. } else if(param == 'cmi.student_data._children'){
  549. // ---- cmi.student_data._children
  550. result = 'mastery_score,max_time_allowed';
  551. } else if(param == 'cmi.student_data.mastery_score'){
  552. // ---- cmi.student_data.mastery_score
  553. result = olms.mastery_score;
  554. } else if(param == 'cmi.student_data.max_time_allowed'){
  555. // ---- cmi.student_data.max_time_allowed
  556. result = olms.max_time_allowed;
  557. } else if(param == 'cmi.interactions._count'){
  558. // ---- cmi.interactions._count
  559. result = olms.interactions.length;
  560. } else if(param == 'cmi.interactions._children'){
  561. // ---- cmi.interactions._children
  562. result = 'id,time,type,correct_responses,weighting,student_response,result,latency';
  563. } else{
  564. // ---- anything else
  565. // Invalid argument error
  566. olms.G_LastError = G_InvalidArgumentError ;
  567. olms.G_LastErrorString = G_InvalidArgumentErrorMessage;
  568. logit_scorm("LMSGetValue ('"+param+"') Error '"+G_InvalidArgumentErrorMessage+"'",1);
  569. result = '';
  570. return result;
  571. }
  572. logit_scorm("LMSGetValue ('"+param+"') returned '"+result+"'",1);
  573. return result;
  574. }
  575. /**
  576. * Twin sister of LMSGetValue(). Only provided for backwards compatibility.
  577. */
  578. function GetValue(param) {
  579. return LMSGetValue(param);
  580. }
  581. /**
  582. * Sets a SCORM variable's value through a call from the SCO.
  583. * @param string The SCORM variable's name
  584. * @param string The SCORM variable's new value
  585. * @param string 'true','false' or an error code
  586. */
  587. function LMSSetValue(param, val) {
  588. logit_scorm("LMSSetValue ('"+param+"','"+val+"')",0);
  589. logit_scorm("Checking olms.lms_item_id " + olms.lms_item_id);
  590. olms.commit = true; //value has changed, need to re-commit
  591. olms.G_LastError = G_NoError ;
  592. olms.G_LastErrorMessage = 'No error';
  593. return_value = 'false';
  594. if (param == "cmi.core.score.raw") {
  595. olms.score= val;
  596. olms.updatable_vars_list['cmi.core.score.raw']=true;
  597. return_value='true';
  598. } else if ( param == "cmi.core.score.max") {
  599. olms.max = val;
  600. olms.updatable_vars_list['cmi.core.score.max']=true;
  601. return_value='true';
  602. } else if ( param == "cmi.core.score.min") {
  603. olms.min = val;
  604. olms.updatable_vars_list['cmi.core.score.min']=true;
  605. return_value='true';
  606. } else if ( param == "cmi.core.lesson_location" ) {
  607. olms.lesson_location = val;
  608. olms.updatable_vars_list['cmi.core.lesson_location']=true;
  609. return_value = 'true';
  610. } else if ( param == "cmi.core.lesson_status" ) {
  611. olms.lesson_status = val;
  612. olms.updatable_vars_list['cmi.core.lesson_status'] = true;
  613. olms.statusSignalReceived = 1;
  614. return_value='true';
  615. } else if ( param == "cmi.completion_status" ) {
  616. olms.lesson_status = val;
  617. olms.updatable_vars_list['cmi.completion_status']=true;
  618. return_value='true'; //1.3
  619. } else if ( param == "cmi.core.session_time" ) {
  620. olms.session_time = val;
  621. olms.updatable_vars_list['cmi.core.session_time']=true;
  622. return_value='true';
  623. } else if ( param == "cmi.score.scaled") { //1.3
  624. if (val<=1 && val>=-1) {
  625. olms.score = val ;
  626. olms.updatable_vars_list['cmi.score.scaled']=true;
  627. return_value='true';
  628. } else {
  629. return_value='false';
  630. }
  631. } else if ( param == "cmi.success_status" ) {
  632. success_status = val;
  633. olms.updatable_vars_list['cmi.success_status']=true;
  634. return_value='true'; //1.3
  635. } else if ( param == "cmi.suspend_data") {
  636. olms.suspend_data = val;
  637. olms.updatable_vars_list['cmi.suspend_data'] = true;
  638. return_value='true';
  639. } else if ( param == "cmi.core.exit" ) {
  640. olms.lms_item_core_exit = val;
  641. olms.updatable_vars_list['cmi.core.exit']=true;
  642. return_value='true';
  643. } else if ( param == "cmi.core.student_id" ) {
  644. olms.G_LastError = G_ElementIsReadOnly;
  645. } else if ( param == "cmi.core.student_name" ) {
  646. olms.G_LastError = G_ElementIsReadOnly;
  647. } else if ( param == "cmi.core.credit" ) {
  648. olms.G_LastError = G_ElementIsReadOnly;
  649. } else if ( param == "cmi.core.entry" ) {
  650. olms.G_LastError = G_ElementIsReadOnly;
  651. } else if ( param == "cmi.core.total_time" ) {
  652. olms.G_LastError = G_ElementIsReadOnly;
  653. } else if ( param == "cmi.core.lesson_mode" ) {
  654. olms.G_LastError = G_ElementIsReadOnly;
  655. } else if ( param == "cmi.comments_from_lms" ) {
  656. olms.G_LastError = G_ElementIsReadOnly;
  657. } else if ( param == "cmi.student_data.time_limit_action" ) {
  658. olms.G_LastError = G_ElementIsReadOnly;
  659. } else if ( param == "cmi.student_data.mastery_score" ) {
  660. olms.G_LastError = G_ElementIsReadOnly;
  661. } else if ( param == "cmi.student_data.max_time_allowed" ) {
  662. olms.G_LastError = G_ElementIsReadOnly;
  663. } else if ( param == "cmi.student_preference._children" ) {
  664. olms.G_LastError = G_ElementIsReadOnly;
  665. } else if ( param == "cmi.launch_data" ) {
  666. olms.G_LastError = G_ElementIsReadOnly;
  667. } else {
  668. var myres = new Array();
  669. if(myres = param.match(/cmi.interactions.(\d+).(id|time|type|correct_responses|weighting|student_response|result|latency)(.*)/)) {
  670. olms.updatable_vars_list['interactions']=true;
  671. elem_id = myres[1];
  672. //interactions setting should start at 0
  673. if(elem_id > olms.interactions.length) {
  674. /*
  675. olms.G_LastError = G_InvalidArgumentError;
  676. olms.G_LastErrorString = 'Invalid argument (interactions)';
  677. return_value = false;
  678. */
  679. olms.interactions[0] = ['0','','','','','','',''];
  680. }
  681. if(olms.interactions[elem_id] == null) {
  682. olms.interactions[elem_id] = ['','','','','','','',''];
  683. //id(0), type(1), time(2), weighting(3),correct_responses(4),student_response(5),result(6),latency(7)
  684. olms.interactions[elem_id][4] = new Array();
  685. }
  686. elem_attrib = myres[2];
  687. switch (elem_attrib) {
  688. case "id":
  689. olms.interactions[elem_id][0] = val;
  690. logit_scorm("Interaction "+elem_id+"'s id updated",2);
  691. return_value='true';
  692. break;
  693. case "time":
  694. olms.interactions[elem_id][2] = val;
  695. logit_scorm("Interaction "+elem_id+"'s time updated",2);
  696. return_value='true';
  697. break;
  698. case "type":
  699. olms.interactions[elem_id][1] = val;
  700. logit_scorm("Interaction "+elem_id+"'s type updated",2);
  701. return_value='true';
  702. break;
  703. case "correct_responses":
  704. // Add at the end of the array
  705. olms.interactions[elem_id][4][olms.interactions[elem_id][4].length] = val;
  706. logit_scorm("Interaction "+elem_id+"'s correct_responses not updated",2);
  707. return_value='true';
  708. break;
  709. case "weighting":
  710. olms.interactions[elem_id][3] = val;
  711. logit_scorm("Interaction "+elem_id+"'s weighting updated",2);
  712. return_value='true';
  713. break;
  714. case "student_response":
  715. olms.interactions[elem_id][5] = ''+val;
  716. logit_scorm("Interaction "+elem_id+"'s student_response updated",2);
  717. return_value='true';
  718. break;
  719. case "result":
  720. olms.interactions[elem_id][6] = val;
  721. logit_scorm("Interaction "+elem_id+"'s result updated",2);
  722. return_value='true';
  723. break;
  724. case "latency":
  725. olms.interactions[elem_id][7] = val;
  726. logit_scorm("Interaction "+elem_id+"'s latency updated",2);
  727. return_value='true';
  728. break;
  729. default:
  730. olms.G_LastError = G_NotImplementedError;
  731. olms.G_LastErrorString = 'Not implemented yet';
  732. }
  733. } else if(param.substring(0,15)== 'cmi.objectives.') {
  734. var myres = '';
  735. olms.updatable_vars_list['objectives']=true;
  736. if(myres = param.match(/cmi.objectives.(\d+).(id|score|status)(.*)/)) {
  737. obj_id = myres[1];
  738. //objectives setting should start at 0
  739. if(obj_id > olms.item_objectives.length) {
  740. olms.G_LastError = G_InvalidArgumentError;
  741. olms.G_LastErrorString = 'Invalid argument (objectives)';
  742. return_value = false;
  743. } else {
  744. req_type = myres[2];
  745. if(obj_id == null || obj_id == '') {
  746. ;//do nothing
  747. } else {
  748. if(olms.item_objectives[obj_id]==null) {
  749. olms.item_objectives[obj_id] = ['','','','',''];
  750. }
  751. if (req_type == "id") {
  752. //olms.item_objectives[obj_id][0] = val.substring(51,57);
  753. olms.item_objectives[obj_id][0] = val;
  754. logit_scorm("Objective "+obj_id+"'s id updated",2);
  755. return_value = 'true';
  756. } else if ( req_type == "score" ) {
  757. if (myres[3] == '._children'){
  758. return_value = '';
  759. olms.G_LastError = G_InvalidSetValue;
  760. olms.G_LastErrorString = 'Invalid set value, element is a keyword';
  761. } else if (myres[3] == '.raw'){
  762. olms.item_objectives[obj_id][2] = val;
  763. logit_scorm("Objective "+obj_id+"'s score raw updated",2);
  764. return_value = 'true';
  765. } else if (myres[3] == '.max'){
  766. olms.item_objectives[obj_id][3] = val;
  767. logit_scorm("Objective "+obj_id+"'s score max updated",2);
  768. return_value = 'true';
  769. } else if (myres[3] == '.min'){
  770. olms.item_objectives[obj_id][4] = val;
  771. logit_scorm("Objective "+obj_id+"'s score min updated",2);
  772. return_value = 'true';
  773. } else {
  774. return_value = '';
  775. olms.G_LastError = G_NotImplementedError;
  776. olms.G_LastErrorString = 'Not implemented yet';
  777. }
  778. } else if ( req_type == "status" ) {
  779. olms.item_objectives[obj_id][1] = val;
  780. logit_scorm("Objective "+obj_id+"'s status updated",2);
  781. return_value = 'true';
  782. } else {
  783. olms.G_LastError = G_NotImplementedError;
  784. olms.G_LastErrorString = 'Not implemented yet';
  785. }
  786. }
  787. }
  788. }
  789. } else {
  790. olms.G_LastError = G_NotImplementedError;
  791. olms.G_LastErrorString = G_NotImplementedErrorMessage;
  792. }
  793. }
  794. <?php
  795. if ($oLP->force_commit == 1) {
  796. echo " var mycommit = LMSCommit('force');";
  797. }
  798. ?>
  799. return return_value;
  800. }
  801. /**
  802. * Twin sister of LMSSetValue(). Only provided for backwards compatibility.
  803. */
  804. function SetValue(param, val) {
  805. return LMSSetValue(param, val);
  806. }
  807. /**
  808. * Saves the current data from JS memory to the LMS database
  809. */
  810. function savedata(item_id) {
  811. // Origin can be 'commit', 'finish' or 'terminate' (depending on the calling function)
  812. logit_lms('function savedata(' + item_id + ')', 3);
  813. // Status is NOT modified here see the lp_ajax_save_item.php file
  814. if (olms.lesson_status != '') {
  815. //olms.updatable_vars_list['cmi.core.lesson_status'] = true;
  816. }
  817. old_item_id = olms.info_lms_item[0];
  818. var item_to_save = olms.lms_item_id;
  819. logit_lms('item_to_save (original value): ' + item_to_save, 3);
  820. // If saving session_time value, we assume that all the new info is about
  821. // the old item, not the current one
  822. // if (olms.session_time != '' && olms.session_time != '0') {
  823. if (olms.switch_finished == 0) {
  824. logit_lms('item_to_save (changed to): ' + old_item_id, 3);
  825. item_to_save = old_item_id;
  826. }
  827. //Original behaviour
  828. // xajax_save_item_scorm(olms.lms_lp_id, olms.lms_user_id, olms.lms_view_id, old_item_id);
  829. // Modified version
  830. xajax_save_item_scorm(
  831. olms.lms_lp_id,
  832. olms.lms_user_id,
  833. olms.lms_view_id,
  834. item_to_save,
  835. olms.lms_session_id,
  836. olms.lms_course_id,
  837. olms.finishSignalReceived,
  838. olms.userNavigatesAway,
  839. olms.statusSignalReceived
  840. );
  841. olms.info_lms_item[1] = olms.lms_item_id;
  842. if (olms.item_objectives.length > 0) {
  843. xajax_save_objectives(
  844. olms.lms_lp_id,
  845. olms.lms_user_id,
  846. olms.lms_view_id,
  847. old_item_id,
  848. olms.item_objectives
  849. );
  850. }
  851. olms.execute_stats = false;
  852. // Clean array
  853. olms.variable_to_send = new Array();
  854. }
  855. /**
  856. * Send the Commit signal to the LMS (save the data for this element without
  857. * closing the current process)
  858. * From SCORM 1.2 RTE: If the API Adapter is caching values received from the
  859. * SCO via an LMSSetValue(), this call requires that any values not yet
  860. * persisted by the LMS be persisted.
  861. * @param string Must be empty string for conformance with SCORM 1.2
  862. */
  863. function LMSCommit(val) {
  864. logit_scorm('LMSCommit() + val');
  865. olms.G_LastError = G_NoError ;
  866. olms.G_LastErrorMessage = 'No error';
  867. savedata(olms.lms_item_id);
  868. reinit_updatable_vars_list();
  869. //now changes have been commited, no need to update until next SetValue()
  870. //commit = 'false' ;
  871. return('true');
  872. }
  873. /**
  874. * Twin sister of LMSCommit(). Only provided for backwards compatibility.
  875. */
  876. function Commit(val) {
  877. return LMSCommit(val);
  878. }
  879. /**
  880. * Send the closure signal to the LMS. This saves the data and closes the current SCO.
  881. * From SCORM 1.2 RTE: The SCO must call this when it has determined that it no
  882. * longer needs to communicate with the LMS, if it successfully called
  883. * LMSInitialize at any previous point. This call signifies two things:
  884. * 1.The SCO can be assured that any data set using LMSSetValue() calls has been persisted by the LMS.
  885. * 2.The SCO has finished communicating with the LMS.
  886. * @param string
  887. */
  888. function LMSFinish(val) {
  889. olms.G_LastError = G_NoError ;
  890. olms.G_LastErrorMessage = 'No error';
  891. olms.finishSignalReceived = 1;
  892. // if olms.commit == false, then the SCORM didn't ask for a commit, so we
  893. // should at least report that
  894. if ( !olms.commit ) {
  895. logit_scorm('LMSFinish() (no LMSCommit())',1);
  896. }
  897. logit_scorm('LMSFinish() called on item ' + olms.lms_item_id, 0);
  898. savedata(olms.lms_item_id);
  899. //reinit the commit detector flag
  900. olms.commit = false;
  901. //reinit the list of modified variables
  902. reinit_updatable_vars_list();
  903. return('true');
  904. }
  905. /**
  906. * Twin sister of LMSFinish(). Only provided for backwards compatibility.
  907. */
  908. function Finish(val) {
  909. return LMSFinish(val);
  910. }
  911. /**
  912. * Returns the last error code as a string
  913. * @return string Error code
  914. */
  915. function LMSGetLastError() {
  916. var error = olms.G_LastError.toString();
  917. logit_scorm('LMSGetLastError() returned: ' + error, 1);
  918. return error;
  919. }
  920. /**
  921. * Twin sister of LMSGetLastError(). Only provided for backwards compatibility.
  922. */
  923. function GetLastError() {
  924. return LMSGetLastError();
  925. }
  926. /**
  927. * Returns the last error code literal for a given error code
  928. * @param int Error code
  929. * @return string Last error
  930. */
  931. function LMSGetErrorString(errCode){
  932. logit_scorm('LMSGetErrorString()',1);
  933. return(olms.G_LastErrorString);
  934. }
  935. /**
  936. * Twin sister of LMSGetErrorString(). Only provided for backwards compatibility.
  937. */
  938. function GetErrorString(errCode){
  939. return LMSGetErrorString(errCode);
  940. }
  941. /**
  942. * Returns a more explanatory, full English, error message
  943. * @param int Error code
  944. * @return string Diagnostic
  945. */
  946. function LMSGetDiagnostic(errCode){
  947. logit_scorm('LMSGetDiagnostic()',1);
  948. return(API.LMSGetLastError());
  949. }
  950. /**
  951. * Twin sister of LMSGetDiagnostic(). Only provided for backwards compatibility.
  952. */
  953. function GetDiagnostic(errCode){
  954. return LMSGetDiagnostic(errCode);
  955. }
  956. /**
  957. * Acts as a "commit"
  958. * This function is not standard SCORM 1.2 and is probably deprecated in all
  959. * meanings of the term.
  960. * @return string 'true' or 'false', depening on whether the LMS has initialized the SCORM process or not
  961. */
  962. function Terminate() {
  963. if (olms.lms_initialized == 0) {
  964. olms.G_LastError = G_NotInitialized;
  965. olms.G_LastErrorMessage = G_NotInitializedMessage;
  966. logit_scorm('Error '+ G_NotInitialized + G_NotInitializedMessage, 0);
  967. return('false');
  968. } else {
  969. logit_scorm('Terminate()',0);
  970. olms.G_LastError = G_NoError ;
  971. olms.G_LastErrorMessage = 'No error';
  972. olms.commit = true;
  973. savedata(olms.lms_item_id);
  974. return ('true');
  975. }
  976. }
  977. /**
  978. * LMS-specific code that deals with event handling and inter-frames
  979. * messaging/refreshing.
  980. * Note that from now on, the LMS JS code in this library will act as
  981. * a controller, of the MVC pattern, and receive all requests for frame
  982. * updates, then redispatch to any frame concerned.
  983. */
  984. /**
  985. * Defining the AJAX-object class to be made available from other frames
  986. */
  987. function XAJAXobject() {
  988. this.xajax_switch_item_details = xajax_switch_item_details;
  989. this.switch_item = switch_item;
  990. this.xajax_save_objectives = xajax_save_objectives;
  991. this.xajax_save_item = xajax_save_item;
  992. }
  993. /**
  994. * Cross-browser event handling by Scott Andrew
  995. * @param element Element that needs an event attached
  996. * @param string Event type (load, unload, click, keyDown, ...)
  997. * @param string Function name (the event handler)
  998. * @param string used in addEventListener
  999. */
  1000. function addEvent(elm, evType, fn, useCapture){
  1001. if (elm.addEventListener){
  1002. elm.addEventListener(evType, fn, useCapture);
  1003. return true;
  1004. } else if (elm.attachEvent) {
  1005. var r = elm.attachEvent('on' + evType, fn);
  1006. } else{
  1007. elm['on'+evType] = fn;
  1008. }
  1009. }
  1010. /**
  1011. * Add listeners to the page objects. This has to be defined for
  1012. * the current context as it acts on objects that should exist
  1013. * on the page
  1014. * possibly deprecated
  1015. * @todo Try to use $(document).unload(lms_save_asset()) instead of the addEvent() method
  1016. */
  1017. function addListeners(){
  1018. //exit if the browser doesn't support ID or tag retrieval
  1019. logit_lms('Entering addListeners()', 3);
  1020. if (!document.getElementsByTagName){
  1021. logit_lms("getElementsByTagName not available", 2);
  1022. return;
  1023. }
  1024. if (!document.getElementById){
  1025. logit_lms("getElementById not available", 2);
  1026. return;
  1027. }
  1028. //assign event handlers to objects
  1029. if (olms.lms_lp_type==1 || olms.lms_item_type=='asset' || olms.lms_item_type == 'document') {
  1030. logit_lms('Chamilo LP or asset');
  1031. //if this path is a Chamilo learnpath, then start manual save
  1032. //when something is loaded in there
  1033. addEvent(window, 'unload', lms_save_asset,false);
  1034. logit_lms('Added event listener lms_save_asset() on window unload', 3);
  1035. }
  1036. logit_lms('Quitting addListeners()');
  1037. }
  1038. /**
  1039. * Save a Chamilo learnpath item's time and mark as completed upon
  1040. * leaving it
  1041. */
  1042. function lms_save_asset() {
  1043. // only for Chamilo lps
  1044. if (olms.execute_stats) {
  1045. olms.execute_stats = false;
  1046. } else {
  1047. olms.execute_stats = true;
  1048. }
  1049. //For scorms do not show stats
  1050. if (olms.lms_lp_type == 2 && olms.lms_lp_item_type != 'document') {
  1051. olms.execute_stats = false;
  1052. }
  1053. if (olms.lms_item_type == 'quiz') {
  1054. olms.execute_stats = true;
  1055. }
  1056. if (olms.lms_lp_type == 1 || olms.lms_item_type == 'asset' || olms.lms_item_type == 'document') {
  1057. logit_lms('lms_save_asset');
  1058. logit_lms('execute_stats :'+ olms.execute_stats);
  1059. xajax_save_item(
  1060. olms.lms_lp_id,
  1061. olms.lms_user_id,
  1062. olms.lms_view_id,
  1063. olms.lms_item_id,
  1064. olms.score,
  1065. olms.max,
  1066. olms.min,
  1067. olms.lesson_status,
  1068. olms.session_time,
  1069. olms.suspend_data,
  1070. olms.lesson_location,
  1071. olms.interactions,
  1072. olms.lms_item_core_exit,
  1073. olms.lms_item_type,
  1074. olms.session_id,
  1075. olms.course_id
  1076. );
  1077. if (olms.item_objectives.length>0) {
  1078. xajax_save_objectives(
  1079. olms.lms_lp_id,
  1080. olms.lms_user_id,
  1081. olms.lms_view_id,
  1082. olms.lms_item_id,
  1083. olms.item_objectives
  1084. );
  1085. }
  1086. }
  1087. }
  1088. /**
  1089. * Save a Chamilo learnpath item's time and mark as completed upon leaving it.
  1090. * Same function as lms_save_asset() but saves it with empty params
  1091. * to use values set from another side in the database. Only used by Chamilo quizzes.
  1092. * Also save the score locally because it hasn't been done through SetValue().
  1093. * Saving the status will be dealt with by the XAJAX function.
  1094. */
  1095. function chamilo_void_save_asset(score, max, min, status) {
  1096. logit_lms('chamilo_void_save_asset('+score+','+max+','+min+','+status+')', 3);
  1097. olms.score = score;
  1098. if ((max == null) || (max == '')){
  1099. max = 100;
  1100. }
  1101. if ((min == null) || (min == '')){
  1102. min = 0;
  1103. }
  1104. // Assume a default of 100, otherwise the score will not get saved (see lpi->set_score())
  1105. xajax_save_item(
  1106. olms.lms_lp_id,
  1107. olms.lms_user_id,
  1108. olms.lms_view_id,
  1109. olms.lms_item_id,
  1110. score,
  1111. max,
  1112. min,
  1113. status
  1114. );
  1115. }
  1116. /**
  1117. * Logs information about SCORM messages into the log frame
  1118. * @param string Message to log
  1119. * @param integer Priority (0 for top priority, 3 for lowest)
  1120. */
  1121. function logit_scorm(message, priority) {
  1122. if (scorm_logs) {
  1123. log_in_log("SCORM: " + message, priority);
  1124. }
  1125. return false;
  1126. }
  1127. function log_in_log(message, priority) {
  1128. // Colorize a little
  1129. var color = "color: black";
  1130. switch (priority) {
  1131. case 0:
  1132. color = "color:red;font-weight:bold";
  1133. break;
  1134. case 1:
  1135. color = "color:orange";
  1136. break;
  1137. case 2:
  1138. color = "color:green";
  1139. break;
  1140. case 3:
  1141. color = "color:blue";
  1142. break;
  1143. }
  1144. if (this.console) {
  1145. // Log in console with syntax colouring
  1146. console.log("%c"+message, color);
  1147. } else {
  1148. window.console.log(message);
  1149. }
  1150. }
  1151. /**
  1152. * Logs information about LMS activity into the log frame
  1153. * @param string Message to log
  1154. * @param integer Priority (0 for top priority, 3 for lowest)
  1155. */
  1156. function logit_lms(message, priority){
  1157. if (scorm_logs) {
  1158. log_in_log("LMS: " + message + ' (#lms_item_id = '+olms.lms_item_id+')', priority);
  1159. }
  1160. return false;
  1161. }
  1162. /**
  1163. * Update the Table Of Contents frame, by changing CSS styles, mostly
  1164. * @param string Action to be taken
  1165. * @param integer Item id to update
  1166. */
  1167. function update_toc(update_action, update_id, change_ids) {
  1168. if (!change_ids || change_ids != 'no') {
  1169. change_ids = 'yes';
  1170. }
  1171. var myelem = $("#toc_"+update_id);
  1172. logit_lms('update_toc("'+update_action+'", '+update_id+')',2);
  1173. if (update_id != 0) {
  1174. // Switch function is broken
  1175. if (update_action == "unhighlight" || update_action == "highlight") {
  1176. if (update_action == "unhighlight") {
  1177. myelem.removeClass('scorm_highlight');
  1178. } else {
  1179. if (change_ids=='yes') {
  1180. olms.lms_next_item = update_id;
  1181. olms.lms_previous_item = update_id;
  1182. }
  1183. myelem.addClass('scorm_highlight');
  1184. }
  1185. } else {
  1186. myelem.removeClass("scorm_not_attempted scorm_incomplete scorm_completed scorm_failed scorm_passed");
  1187. if (update_action == "not attempted") {
  1188. myelem.addClass('scorm_not_attempted');
  1189. } else if (update_action == "incomplete") {
  1190. myelem.addClass('scorm_not_attempted');
  1191. } else if (update_action == "completed") {
  1192. myelem.addClass('scorm_completed');
  1193. } else if (update_action == "failed") {
  1194. myelem.addClass('scorm_failed');
  1195. } else if (update_action == "passed") {
  1196. myelem.addClass('scorm_completed');
  1197. } else if (update_action == "browsed") {
  1198. myelem.addClass('scorm_completed');
  1199. } else {
  1200. logit_lms('Update action unknown',1);
  1201. }
  1202. }
  1203. }
  1204. return true;
  1205. }
  1206. /**
  1207. * Update the stats frame using a reload of the frame to avoid unsynched data
  1208. */
  1209. function update_stats() {
  1210. logit_lms('update_stats()');
  1211. if (olms.execute_stats) {
  1212. try {
  1213. cont_f = document.getElementById('content_id');
  1214. cont_f.src = "lp_controller.php?action=stats";
  1215. cont_f.reload();
  1216. } catch (e) {
  1217. return false;
  1218. }
  1219. }
  1220. olms.execute_stats = false;
  1221. }
  1222. /**
  1223. * Update the stats frame using a reload of the frame to avoid unsynched data
  1224. */
  1225. function update_stats_page() {
  1226. logit_lms('update_stats_page',3);
  1227. var myframe = document.getElementById('content_id');
  1228. var mysrc = myframe.location.href;
  1229. if(mysrc == 'lp_controller.php?action=stats'){
  1230. if(myframe && myframe.src){
  1231. var mysrc = myframe.src;
  1232. myframe.src = mysrc;
  1233. }
  1234. // = mysrc; //refresh page
  1235. }
  1236. return true;
  1237. }
  1238. /**
  1239. * Updates the progress bar with the new status. Prevents the need of a page refresh and flickering
  1240. * @param integer Number of completed items
  1241. * @param integer Number of items in total
  1242. * @param string Display mode (absolute 'abs' or percentage '%').Defaults to %
  1243. */
  1244. function update_progress_bar(nbr_complete, nbr_total, mode) {
  1245. logit_lms('update_progress_bar('+nbr_complete+', '+nbr_total+', '+mode+')',3);
  1246. logit_lms(
  1247. 'update_progress_bar with params: lms_lp_id= ' + olms.lms_lp_id +
  1248. ', lms_view_id= '+ olms.lms_view_id + ' lms_user_id= '+ olms.lms_user_id,
  1249. 3
  1250. );
  1251. if (mode == '') {
  1252. mode='%';
  1253. }
  1254. if (nbr_total == 0) {
  1255. nbr_total=1;
  1256. }
  1257. var percentage = (nbr_complete/nbr_total)*100;
  1258. percentage = Math.round(percentage);
  1259. var progress_bar = $("#progress_bar_value");
  1260. progress_bar.css('width', percentage + "%");
  1261. var mytext = '';
  1262. switch(mode){
  1263. case 'abs':
  1264. mytext = nbr_complete + '/' + nbr_total;
  1265. break;
  1266. case '%':
  1267. default:
  1268. mytext = percentage + '%';
  1269. break;
  1270. }
  1271. progress_bar.html(mytext);
  1272. return true;
  1273. }
  1274. /**
  1275. * Update the gamification values (number of stars and score)
  1276. */
  1277. function updateGamificationValues()
  1278. {
  1279. var fetchValues = $.ajax(
  1280. '<?php echo api_get_path(WEB_AJAX_PATH); ?>lp.ajax.php' + courseUrl,
  1281. {
  1282. dataType: 'json',
  1283. data: {
  1284. a: 'update_gamification'
  1285. }
  1286. });
  1287. $.when(fetchValues).done(function (values) {
  1288. if (values.stars > 0) {
  1289. $('#scorm-gamification .fa-star:nth-child(' + values.stars + ')').addClass('level');
  1290. }
  1291. $('#scorm-gamification .col-xs-4').text(values.score);
  1292. });
  1293. }
  1294. /**
  1295. * Analyses the variables that have been modified through this SCO's life and
  1296. * put them into an array for later shipping to lp_ajax_save_item.php
  1297. * @return array Array of SCO variables
  1298. */
  1299. function process_scorm_values() {
  1300. logit_scorm('process_scorm_values()');
  1301. for (i=0; i < olms.scorm_variables.length; i++) {
  1302. if (olms.updatable_vars_list[olms.scorm_variables[i]]) {
  1303. olms.variable_to_send.push(olms.scorm_variables[i]);
  1304. }
  1305. }
  1306. return olms.variable_to_send;
  1307. }
  1308. /**
  1309. * Reinitializes the SCO's modified variables to an empty list.
  1310. * @return void
  1311. * @uses The global updatable_vars_list array to register this
  1312. */
  1313. function reinit_updatable_vars_list() {
  1314. logit_scorm('Cleaning updatable_vars_list: reinit_updatable_vars_list');
  1315. for (i=0;i < olms.scorm_variables.length;i++) {
  1316. if (olms.updatable_vars_list[olms.scorm_variables[i]]) {
  1317. olms.updatable_vars_list[olms.scorm_variables[i]]=false;
  1318. }
  1319. }
  1320. olms.lesson_status = 'not attempted';
  1321. }
  1322. /**
  1323. * Function that handles the saving of an item and switching from an item to another.
  1324. * Once called, this function should be able to do the whole process of
  1325. * (1) saving the current item,
  1326. * (2) refresh all the values inside the SCORM API object,
  1327. * (3) open the new item into the content_id frame,
  1328. * (4) refresh the table of contents
  1329. * (5) refresh the progress bar (completion)
  1330. * (6) refresh the message frame
  1331. * @param integer Chamilo ID for the current item
  1332. * @param string This parameter can be a string specifying the next
  1333. * item (like 'next', 'previous', 'first' or 'last') or the id to the next item
  1334. */
  1335. function switch_item(current_item, next_item)
  1336. {
  1337. if (olms.lms_initialized == 0) {
  1338. // Fix error when flash is not loaded and SCO is not started BT#14944
  1339. olms.G_LastError = G_NotInitialized;
  1340. olms.G_LastErrorMessage = G_NotInitializedMessage;
  1341. logit_scorm('Error '+ G_NotInitialized + G_NotInitializedMessage, 0);
  1342. window.location.reload(false);
  1343. return false;
  1344. }
  1345. olms.switch_finished = 0; //only changed back once LMSInitialize() happens
  1346. // backup these params
  1347. var orig_current_item = current_item;
  1348. var orig_next_item = next_item;
  1349. var orig_lesson_status = olms.lesson_status;
  1350. var orig_item_type = olms.lms_item_types['i'+current_item];
  1351. var next_item_type = olms.lms_item_types['i'+next_item];
  1352. if (olms.statusSignalReceived == 0 && olms.lesson_status != 'not attempted') {
  1353. // In this situation, the status can be considered set as it was clearly
  1354. // set in a previous stage
  1355. olms.statusSignalReceived = 1;
  1356. }
  1357. logit_lms('switch_item() called with params '+olms.lms_item_id+' and '+next_item+'',2);
  1358. /*
  1359. There are four "cases" for switching items:
  1360. (1) asset switching to asset
  1361. We need to save, then switch
  1362. (2) asset switching to sco
  1363. We need to save, switching not necessary (LMSInitialize does the job)
  1364. (3) sco switching to asset
  1365. We need to switch the document in the content frame, but we cannot
  1366. switch the item details, otherwise the LMSFinish() call (that *must*
  1367. be triggered by the SCO when it unloads) will use bad values. However,
  1368. we need to load the new asset's context once the SCO has unloaded
  1369. (4) sco switching to sco
  1370. We don't need to switch nor commit, LMSFinish() on unload and
  1371. LMSInitialize on load will do the job
  1372. In any case, we need to change the current document frame.
  1373. These cases, although clear here, are however very difficult to implement
  1374. */
  1375. if (orig_item_type != 'sco') {
  1376. if (next_item_type != 'sco' ) {
  1377. logit_lms('Case 1 - current != sco and next != sco');
  1378. } else {
  1379. logit_lms('Case 2 - current != sco but next == sco');
  1380. }
  1381. xajax_save_item(
  1382. olms.lms_lp_id,
  1383. olms.lms_user_id,
  1384. olms.lms_view_id,
  1385. olms.lms_item_id,
  1386. olms.score,
  1387. olms.max,
  1388. olms.min,
  1389. olms.lesson_status,
  1390. olms.asset_timer,
  1391. olms.suspend_data,
  1392. olms.lesson_location,
  1393. olms.interactions,
  1394. olms.lms_item_core_exit,
  1395. orig_item_type,
  1396. olms.session_id,
  1397. olms.course_id,
  1398. olms.finishSignalReceived,
  1399. 1,
  1400. olms.statusSignalReceived
  1401. );
  1402. xajax_switch_item_details(
  1403. olms.lms_lp_id,
  1404. olms.lms_user_id,
  1405. olms.lms_view_id,
  1406. olms.lms_item_id,
  1407. next_item
  1408. );
  1409. } else {
  1410. if (next_item_type != 'sco') {
  1411. logit_lms('Case 3 - current == sco but next != sco');
  1412. } else {
  1413. logit_lms('Case 4 - current == sco and next == sco');
  1414. }
  1415. // Setting userNavigatesAway = 1
  1416. xajax_save_item_scorm(
  1417. olms.lms_lp_id,
  1418. olms.lms_user_id,
  1419. olms.lms_view_id,
  1420. olms.lms_item_id,
  1421. olms.lms_session_id,
  1422. olms.lms_course_id,
  1423. olms.finishSignalReceived,
  1424. 1,
  1425. olms.statusSignalReceived
  1426. );
  1427. reinit_updatable_vars_list();
  1428. xajax_switch_item_toc(
  1429. olms.lms_lp_id,
  1430. olms.lms_user_id,
  1431. olms.lms_view_id,
  1432. olms.lms_item_id,
  1433. next_item
  1434. );
  1435. if (olms.item_objectives.length>0) {
  1436. xajax_save_objectives(
  1437. olms.lms_lp_id,
  1438. olms.lms_user_id,
  1439. olms.lms_view_id,
  1440. olms.lms_item_id,
  1441. olms.item_objectives
  1442. );
  1443. }
  1444. }
  1445. /**
  1446. * Because of SCORM 1.2's special rule about unsent commits and the fact
  1447. * that a SCO should be SET TO 'completed' IF NO STATUS WAS SENT (and
  1448. * then some checks have to be done on score), we have to force a
  1449. * special commit here to avoid getting to the next element with a
  1450. * missing prerequisite. The 'onunload' event is treated with
  1451. * savedata_onunload(), and doesn't need to be triggered at any
  1452. * particular time, but here we are in the case of switching to another
  1453. * item, so this is particularly important to complete the element in
  1454. * time.
  1455. * However, this cannot be initiated from the JavaScript, mainly
  1456. * because another onunload event can be triggered by the SCO itself,
  1457. * which can set, for example, the status to incomplete while the
  1458. * status has already been set to "completed" by the hand-made
  1459. * savedata() (and then the status cannot be "incompleted"
  1460. * anymore)
  1461. */
  1462. /*
  1463. if (olms.lms_item_type=='sco' &&
  1464. olms.lesson_status != 'completed' &&
  1465. olms.lesson_status != 'passed' &&
  1466. olms.lesson_status != 'browsed' &&
  1467. olms.lesson_status != 'incomplete' &&
  1468. olms.lesson_status != 'failed'
  1469. ) {
  1470. // savedata() with olms.finishSignalReceived == 1 treats the special
  1471. // condition and saves the new status to the database, so
  1472. // switch_item_details() enjoys the new status
  1473. savedata(olms.lms_item_id);
  1474. }
  1475. xajax_save_item(
  1476. olms.lms_lp_id,
  1477. olms.lms_user_id,
  1478. olms.lms_view_id,
  1479. olms.lms_item_id,
  1480. olms.score, olms.max,
  1481. olms.min,
  1482. olms.lesson_status,
  1483. olms.session_time,
  1484. olms.suspend_data,
  1485. olms.lesson_location,
  1486. olms.interactions,
  1487. olms.lms_item_core_exit,
  1488. orig_item_type,
  1489. olms.session_id,
  1490. olms.course_id,
  1491. olms.finishSignalReceived,
  1492. 1,
  1493. olms.statusSignalReceived
  1494. );
  1495. */
  1496. olms.execute_stats = false;
  1497. // Considering info_lms_item[0] is initially the oldest and info_lms_item[1]
  1498. // is the newest item, and considering we are done switching the items now,
  1499. // we need to update these markers so that the new item is loaded when
  1500. // changing the document in the content frame
  1501. if (olms.info_lms_item[1]==next_item && next_item!='next' && next_item!='previous') {
  1502. olms.info_lms_item[0]=next_item;
  1503. olms.info_lms_item[1]=next_item;
  1504. } else {
  1505. if (next_item!='next' && next_item!='previous') {
  1506. olms.info_lms_item[0]=olms.info_lms_item[1];
  1507. olms.info_lms_item[1]=next_item;
  1508. }
  1509. }
  1510. if (olms.info_lms_item[0]==next_item && next_item!='next' && next_item!='previous') {
  1511. olms.info_lms_item[0]=next_item;
  1512. olms.info_lms_item[1]=next_item;
  1513. } else {
  1514. if (next_item!='next' && next_item!='previous') {
  1515. olms.info_lms_item[0]=olms.info_lms_item[0];
  1516. olms.info_lms_item[1]=next_item;
  1517. }
  1518. }
  1519. //(3) open the new item in the content_id frame
  1520. switch (next_item) {
  1521. case 'next':
  1522. next_item = olms.lms_next_item;
  1523. olms.info_lms_item[0] = olms.info_lms_item[1];
  1524. olms.info_lms_item[1] = olms.lms_next_item;
  1525. break;
  1526. case 'previous':
  1527. next_item = olms.lms_previous_item;
  1528. olms.info_lms_item[0] = olms.info_lms_item[1];
  1529. olms.info_lms_item[1] = olms.lms_previous_item;
  1530. break;
  1531. default:
  1532. break;
  1533. }
  1534. var mysrc = '<?php echo api_get_path(WEB_CODE_PATH); ?>lp/lp_controller.php?action=content&lp_id=' + olms.lms_lp_id +
  1535. '&item_id=' + next_item + '&cidReq=' + olms.lms_course_code + '&id_session=' + olms.lms_session_id;
  1536. var cont_f = $("#content_id");
  1537. <?php if ($oLP->mode == 'fullscreen') {
  1538. ?>
  1539. cont_f = window.open('' + mysrc, 'content_id', 'toolbar=0,location=0,status=0,scrollbars=1,resizable=1');
  1540. cont_f.onload=function(){
  1541. olms.info_lms_item[0]=olms.info_lms_item[1];
  1542. }
  1543. cont_f.onunload=function(){
  1544. olms.info_lms_item[0]=olms.info_lms_item[1];
  1545. }
  1546. <?php
  1547. } else {
  1548. ?>
  1549. log_in_log('loading '+mysrc+' in frame');
  1550. cont_f.attr("src",mysrc);
  1551. <?php
  1552. } ?>
  1553. if (olms.lms_lp_type==1 || olms.lms_item_type == 'asset' || olms.lms_item_type == 'document') {
  1554. xajax_start_timer();
  1555. }
  1556. // (4) refresh the audio player if needed
  1557. $.ajax({
  1558. type: "POST",
  1559. url: "lp_nav.php"+courseUrl+ "&lp_id=" + olms.lms_lp_id,
  1560. data: {
  1561. lp_item: next_item
  1562. },
  1563. beforeSend: function() {
  1564. $.each($('audio'), function () {
  1565. if (this.player && this.player !== undefined) {
  1566. this.player.pause();
  1567. }
  1568. });
  1569. },
  1570. success: function(tmp_data) {
  1571. if ($("#lp_media_file").length != 0) {
  1572. $("#lp_media_file").html(tmp_data);
  1573. }
  1574. LPViewUtils.setHeightLPToc();
  1575. }
  1576. });
  1577. loadForumThread(olms.lms_lp_id, next_item);
  1578. checkCurrentItemPosition(olms.lms_item_id);
  1579. return true;
  1580. }
  1581. /**
  1582. * Hide or show the navigation buttons if the current item is the First or Last
  1583. */
  1584. var checkCurrentItemPosition = function(lpItemId) {
  1585. var currentItem = $.getJSON(
  1586. '<?php echo api_get_path(WEB_AJAX_PATH); ?>lp.ajax.php' + courseUrl,
  1587. {
  1588. a: 'check_item_position',
  1589. lp_item: lpItemId
  1590. }
  1591. ).done(function(parsedResponse,statusText,jqXhr) {
  1592. var position = jqXhr.responseJSON;
  1593. if (position == 'first') {
  1594. $("#scorm-previous").hide();
  1595. $("#scorm-next").show();
  1596. } else if (position == 'none') {
  1597. $("#scorm-previous").show();
  1598. $("#scorm-next").show();
  1599. } else if (position == 'last') {
  1600. $("#scorm-previous").show();
  1601. $("#scorm-next").hide();
  1602. } else if (position == 'both') {
  1603. $("#scorm-previous").hide();
  1604. $("#scorm-next").hide();
  1605. }
  1606. });
  1607. }
  1608. /**
  1609. * Get a forum info when the learning path item has a associated forum
  1610. */
  1611. var loadForumThread = function(lpId, lpItemId) {
  1612. var loadForum = $.getJSON(
  1613. '<?php echo api_get_path(WEB_AJAX_PATH); ?>lp.ajax.php' + courseUrl, {
  1614. a: 'get_forum_thread',
  1615. lp: lpId,
  1616. lp_item: lpItemId
  1617. }
  1618. );
  1619. $.when(loadForum).done(function(forumThreadData) {
  1620. var tabForumLink = $('.lp-view-tabs a[href="#lp-view-forum"]'),
  1621. tabForum = tabForumLink.parent();
  1622. $("#navTabs").show();
  1623. $("#tab-iframe").removeClass("tab-none-forum");
  1624. $("#btn-menu-float").removeClass("none-forum");
  1625. if (forumThreadData.error) {
  1626. tabForumLink.removeAttr('data-toggle');
  1627. tabForum.addClass('disabled');
  1628. $("#navTabs").hide();
  1629. $("#tab-iframe").addClass("tab-none-forum");
  1630. $("#btn-menu-float").addClass("none-forum");
  1631. $('#lp-view-forum').html('');
  1632. return;
  1633. }
  1634. tabForumLink.attr('data-toggle', 'tab');
  1635. tabForum.removeClass('disabled');
  1636. var forumIframe = $('<iframe>').attr({
  1637. width:'100%',
  1638. frameborder:'0',
  1639. scrolling:'yes',
  1640. tabindex:'0',
  1641. id:'chamilo-disqus',
  1642. src: '<?php echo api_get_path(WEB_CODE_PATH); ?>forum/viewthread.php?<?php echo api_get_cidreq(); ?>&' + $.param({
  1643. gradebook: 0,
  1644. origin: 'learnpath',
  1645. forum: forumThreadData.forumId,
  1646. thread: forumThreadData.threadId,
  1647. posts_order: 'desc'
  1648. })
  1649. });
  1650. $('#lp-view-forum').html(forumIframe);
  1651. });
  1652. };
  1653. /**
  1654. * Save a specific item (with its interactions, if any) into the LMS through
  1655. * an AJAX call to lp_ajax_save_item.php.
  1656. * Because of the need to pass an array, we have to build the parameters
  1657. * manually into GET[].
  1658. * This function has a twin sister for SCO elements (xajax_save_item_scorm)
  1659. * which takes into account the interactions.
  1660. * @param int ID of the learning path (for the LMS)
  1661. * @param int ID of the user
  1662. * @param int ID of the view of this learning path
  1663. * @param int ID of the item currently looked at
  1664. * @param float Score
  1665. * @param float Max score
  1666. * @param float Min score
  1667. * @param string Lesson status
  1668. * @param string Current session time (in 'xxxx:xx:xx.xx' format)
  1669. * @param string Suspend data (maximum 255 chars)
  1670. * @param string Lesson location (which page we've reached in the SCO)
  1671. * @param array Interactions
  1672. * @param string Core exit value (up to 4096 chars)
  1673. * @return void
  1674. * @uses lp_ajax_save_item.php through an AJAX call
  1675. */
  1676. function xajax_save_item(
  1677. lms_lp_id,
  1678. lms_user_id,
  1679. lms_view_id,
  1680. lms_item_id,
  1681. score,
  1682. max,
  1683. min,
  1684. lesson_status,
  1685. session_time,
  1686. suspend_data,
  1687. lesson_location,
  1688. interactions,
  1689. lms_item_core_exit,
  1690. item_type,
  1691. session_id,
  1692. course_id,
  1693. finishSignalReceived,
  1694. userNavigatesAway,
  1695. statusSignalReceived
  1696. ) {
  1697. var params = '';
  1698. if (typeof(finishSignalReceived) == 'undefined') {
  1699. finishSignalReceived = 0;
  1700. }
  1701. if (typeof(userNavigatesAway) == 'undefined') {
  1702. userNavigatesAway = 0;
  1703. }
  1704. if (typeof(statusSignalReceived) == 'undefined') {
  1705. statusSignalReceived = 0;
  1706. }
  1707. params += 'lid='+lms_lp_id+'&uid='+lms_user_id+'&vid='+lms_view_id;
  1708. params += '&iid='+lms_item_id+'&s='+score+'&max='+max+'&min='+min;
  1709. params += '&status='+lesson_status+'&t='+session_time;
  1710. params += '&suspend='+suspend_data+'&loc='+lesson_location;
  1711. params += '&core_exit='+lms_item_core_exit;
  1712. params += '&session_id='+session_id;
  1713. params += '&course_id='+course_id;
  1714. params += '&finishSignalReceived='+finishSignalReceived;
  1715. params += '&userNavigatesAway='+userNavigatesAway;
  1716. params += '&statusSignalReceived='+statusSignalReceived;
  1717. if (olms.lms_lp_type == 1 || item_type == 'document' || item_type == 'asset') {
  1718. logit_lms('xajax_save_item with params:' + params, 3);
  1719. $.ajax({
  1720. type:"POST",
  1721. data: params,
  1722. url: "lp_ajax_save_item.php" + courseUrl,
  1723. dataType: "script",
  1724. async: false
  1725. });
  1726. }
  1727. }
  1728. /**
  1729. * Save a SCORM item's variables, getting its SCORM values from
  1730. * updatable_vars_list. Takes interactions into account and considers whether
  1731. * variables have been modified or not.
  1732. * @param int ID of the learning path
  1733. * @param int ID of the user
  1734. * @param int ID of the view
  1735. * @param int ID of the item
  1736. * @param bool 1 if this call comes from a "LMSFinish()" call, 0 or nothing otherwise
  1737. * @return void
  1738. * @uses olms.updatable_vars_list
  1739. * @uses lp_ajax_save_item.php through an AJAX call
  1740. */
  1741. function xajax_save_item_scorm(
  1742. lms_lp_id,
  1743. lms_user_id,
  1744. lms_view_id,
  1745. lms_item_id,
  1746. session_id,
  1747. course_id,
  1748. finishSignalReceived,
  1749. userNavigatesAway,
  1750. statusSignalReceived
  1751. ) {
  1752. if (typeof(finishSignalReceived) == 'undefined') {
  1753. finishSignalReceived = 0;
  1754. }
  1755. if (typeof(userNavigatesAway) == 'undefined') {
  1756. userNavigatesAway = 0;
  1757. }
  1758. if (typeof(statusSignalReceived) == 'undefined') {
  1759. statusSignalReceived = 0;
  1760. }
  1761. var is_interactions='false';
  1762. var params = 'lid='+lms_lp_id+'&uid='+lms_user_id+'&vid='+lms_view_id+'&iid='+lms_item_id;
  1763. // The missing arguments will be ignored by lp_ajax_save_item.php
  1764. //params += '&s=&max=&min=&status=&t=&suspend=&loc=&interact=&core_exit=';
  1765. params += '&session_id='+session_id;
  1766. params += '&course_id='+course_id;
  1767. params += '&finishSignalReceived='+finishSignalReceived;
  1768. params += '&userNavigatesAway='+userNavigatesAway;
  1769. params += '&statusSignalReceived='+statusSignalReceived;
  1770. var my_scorm_values = new Array();
  1771. my_scorm_values = process_scorm_values();
  1772. for (k=0; k < my_scorm_values.length; k++) {
  1773. if (my_scorm_values[k]=='cmi.core.session_time') {
  1774. params += '&t='+olms.session_time;
  1775. } else if (my_scorm_values[k]=='cmi.core.lesson_status' && olms.lesson_status!='') {
  1776. params += '&status='+olms.lesson_status;
  1777. } else if (my_scorm_values[k]=='cmi.core.score.raw') {
  1778. params += '&s='+olms.score;
  1779. } else if (my_scorm_values[k]=='cmi.core.score.max') {
  1780. params += '&max='+olms.max;
  1781. } else if (my_scorm_values[k]=='cmi.core.score.min') {
  1782. params += '&min='+olms.min;
  1783. } else if (my_scorm_values[k]=='cmi.core.lesson_location') {
  1784. params += '&loc='+olms.lesson_location;
  1785. } else if (my_scorm_values[k]=='cmi.completion_status') {
  1786. } else if (my_scorm_values[k]=='cmi.score.scaled') {
  1787. } else if (my_scorm_values[k]=='cmi.suspend_data') {
  1788. // params += '&suspend='+olms.suspend_data;
  1789. // Fixes error when scorm sends text with "+" sign
  1790. params += '&suspend='+encodeURIComponent(olms.suspend_data);
  1791. } else if (my_scorm_values[k]=='cmi.completion_status') {
  1792. } else if (my_scorm_values[k]=='cmi.core.exit') {
  1793. params += '&core_exit='+olms.lms_item_core_exit;
  1794. }
  1795. if (my_scorm_values[k]=='interactions') {
  1796. is_interactions='true';
  1797. } else {
  1798. is_interactions='false';
  1799. }
  1800. }
  1801. if (is_interactions == 'true') {
  1802. interact_string = '';
  1803. temp = '';
  1804. for (i in olms.interactions) {
  1805. interact_string += '&interact['+i+']=';
  1806. interact_temp = '[';
  1807. for (j in olms.interactions[i]) {
  1808. temp = olms.interactions[i][j];
  1809. temp = ''+temp; // if temp == 1 there are problems with indexOf and an integer number
  1810. //this fix when an interaction have ',' i.e: {a,b,c,d} is replace to {a@.|@b@.|@c@.|@d} see DT#4444
  1811. while(temp.indexOf(',') >= 0){
  1812. temp = temp.replace(',','@.|@');
  1813. };
  1814. interact_temp +=temp+',';
  1815. }
  1816. interact_temp = interact_temp.substr(0,(interact_temp.length-2)) + ']';
  1817. // interact_string += encodeURIComponent(interact_temp);
  1818. interact_string += interact_temp;
  1819. }
  1820. //interact_string = encodeURIComponent(interact_string.substr(0,(interact_string.length-1)));
  1821. params += interact_string;
  1822. is_interactions='false';
  1823. }
  1824. logit_lms('xajax_save_item_scorm with params:' + params, 3);
  1825. $.ajax({
  1826. type:"POST",
  1827. data: params,
  1828. url: "lp_ajax_save_item.php" + courseUrl,
  1829. dataType: "script",
  1830. async: false
  1831. });
  1832. params = '';
  1833. my_scorm_values = null;
  1834. }
  1835. /**
  1836. * Starts the timer with the server clock time.
  1837. * @return void
  1838. * @todo check the timer stuff really works and rename function to startTimer()
  1839. * @uses lp_ajax_start_timer.php
  1840. */
  1841. function xajax_start_timer() {
  1842. logit_lms('xajax_start_timer() called',3);
  1843. $.ajax({
  1844. type: "GET",
  1845. url: "lp_ajax_start_timer.php" + courseUrl,
  1846. dataType: "script",
  1847. async: false,
  1848. success: function(time) {
  1849. olms.asset_timer = time;
  1850. olms.asset_timer_total = 0;
  1851. logit_lms('xajax_start_timer result: ' + time,3);
  1852. var date = new Date(time * 1000);
  1853. logit_lms('xajax_start_timer result: ' + date.toString(),3);
  1854. }
  1855. });
  1856. }
  1857. /**
  1858. * Save a specific item's objectives into the LMS through an Synch JAX call
  1859. * @param int ID of the learning path
  1860. * @param int ID of the user
  1861. * @param int ID of the view
  1862. * @param int ID of the item
  1863. * @param array SCO's recorded objectives
  1864. * @uses lp_ajax_save_objectives.php
  1865. */
  1866. function xajax_save_objectives(lms_lp_id,lms_user_id,lms_view_id,lms_item_id,item_objectives) {
  1867. var params = '';
  1868. params += 'lid='+lms_lp_id+'&uid='+lms_user_id+'&vid='+lms_view_id;
  1869. params += '&iid='+lms_item_id;
  1870. obj_string = '';
  1871. logit_lms('xajax_save_objectives with params:' + params, 3);
  1872. for (i in item_objectives){
  1873. obj_string += '&objectives['+i+']=';
  1874. obj_temp = '[';
  1875. for (j in item_objectives[i]) {
  1876. obj_temp += item_objectives[i][j]+',';
  1877. }
  1878. obj_temp = obj_temp.substr(0,(obj_temp.length-2)) + ']';
  1879. obj_string += encodeURIComponent(obj_temp);
  1880. }
  1881. params += obj_string;
  1882. $.ajax({
  1883. type: "POST",
  1884. data: params,
  1885. url: "lp_ajax_save_objectives.php" + courseUrl,
  1886. dataType: "script",
  1887. async: false
  1888. });
  1889. }
  1890. /**
  1891. * Switch between two items through an AJAX call.
  1892. * @param int ID of the learning path
  1893. * @param int ID of the user
  1894. * @param int ID of the view
  1895. * @param int ID of the item
  1896. * @param int ID of the next item
  1897. * @uses lp_ajax_switch_item.php
  1898. */
  1899. function xajax_switch_item_details(lms_lp_id,lms_user_id,lms_view_id,lms_item_id,next_item) {
  1900. var params = {
  1901. 'lid': lms_lp_id,
  1902. 'uid': lms_user_id,
  1903. 'vid': lms_view_id,
  1904. 'iid': lms_item_id,
  1905. 'next': next_item
  1906. };
  1907. logit_lms('xajax_switch_item_details with params:' + params, 3);
  1908. $.ajax({
  1909. type: "POST",
  1910. data: params,
  1911. url: "lp_ajax_switch_item.php" + courseUrl,
  1912. dataType: "script",
  1913. async: false
  1914. });
  1915. }
  1916. /**
  1917. * Switch between two items through an AJAX call, but only update the TOC and
  1918. * progress bar.
  1919. * @param int ID of the learning path
  1920. * @param int ID of the user
  1921. * @param int ID of the view
  1922. * @param int ID of the item
  1923. * @param int ID of the next item
  1924. * @uses lp_ajax_switch_toc.php
  1925. */
  1926. function xajax_switch_item_toc(lms_lp_id, lms_user_id, lms_view_id, lms_item_id, next_item) {
  1927. var params = {
  1928. 'lid': lms_lp_id,
  1929. 'uid': lms_user_id,
  1930. 'vid': lms_view_id,
  1931. 'iid': lms_item_id,
  1932. 'next': next_item
  1933. };
  1934. logit_lms('xajax_switch_item_toc');
  1935. $.ajax({
  1936. type: "POST",
  1937. data: params,
  1938. url: "lp_ajax_switch_item_toc.php" + courseUrl,
  1939. dataType: "script",
  1940. async: false
  1941. });
  1942. }
  1943. /**
  1944. * Allow attach the glossary terms into html document of scorm. This has
  1945. * nothing to do with SCORM itself, and should not interfere w/ SCORM either.
  1946. * @param string automatic or manual values are allowed
  1947. */
  1948. function attach_glossary_into_scorm(type) {
  1949. var f = $('#content_id')[0];
  1950. //Prevents "f is undefined" javascript error
  1951. if (f == null) {
  1952. logit_lms('attach_glossary_into_scorm failed', 0);
  1953. return false;
  1954. }
  1955. try {
  1956. var doc = f.contentWindow ? f.contentWindow.document : f.contentDocument ? f.contentDocument : f.document;
  1957. } catch (ex) { }
  1958. var $frame_content = $('body',doc);
  1959. var my_text=$frame_content.html();
  1960. my_protocol = location.protocol;
  1961. my_pathname=location.pathname;
  1962. work_path = my_pathname.substr(0,my_pathname.indexOf('<?php echo api_get_path(REL_COURSE_PATH); ?>'));
  1963. var ajaxRequestUrl = '<?php echo api_get_path(WEB_CODE_PATH).'glossary/glossary_ajax_request.php'; ?>' + courseUrl;
  1964. if (type == 'automatic') {
  1965. $.ajax({
  1966. contentType: "application/x-www-form-urlencoded",
  1967. beforeSend: function(object) {
  1968. },
  1969. type: "POST",
  1970. url: ajaxRequestUrl,
  1971. data: "glossary_data=true",
  1972. success: function(datas) {
  1973. if (datas.length==0) {
  1974. return false;
  1975. }
  1976. // glossary terms
  1977. data_terms=datas.split("[|.|_|.|-|.|]");
  1978. var complex_array = new Array();
  1979. var cp_complex_array = new Array();
  1980. for(i=0;i < data_terms.length;i++) {
  1981. specific_terms= data_terms[i].split("__|__|");
  1982. var real_term = specific_terms[1]; // glossary term
  1983. var real_code = specific_terms[0]; // glossary id
  1984. complex_array[real_code] = real_term;
  1985. cp_complex_array[real_code] = real_term;
  1986. }
  1987. complex_array.reverse();
  1988. for (var my_index in complex_array) {
  1989. n = complex_array[my_index];
  1990. if (n == null) {
  1991. n = '';
  1992. } else {
  1993. for (var cp_my_index in cp_complex_array) {
  1994. cp_data = cp_complex_array[cp_my_index];
  1995. if (cp_data == null) {
  1996. cp_data = '';
  1997. } else {
  1998. if (cp_data == n) {
  1999. my_index = cp_my_index;
  2000. }
  2001. }
  2002. }
  2003. //alert(n + ' ' + my_index);
  2004. $("iframe").contents().find('body').removeHighlight().highlight(n,my_index)
  2005. }
  2006. }
  2007. var complex_array = new Array();
  2008. $("iframe").contents().find("body").on("click", ".glossary-ajax", function() {
  2009. div_show_id="div_show_id";
  2010. div_content_id="div_content_id";
  2011. $("iframe").contents().find("body").
  2012. append('<div id="div_show_id"><div id="div_content_id">&nbsp;</div></div>');
  2013. show_dialog = $("iframe").contents().find("div#"+div_show_id);
  2014. show_description = $("iframe").contents().find("div#"+div_content_id);
  2015. var $target = $(this);
  2016. if ($("#learning_path_left_zone").is(':visible') ) {
  2017. var extra_left = $("#learning_path_left_zone").width() + 20;
  2018. } else {
  2019. var extra_left = 0;
  2020. }
  2021. show_dialog.dialog({
  2022. autoOpen: false,
  2023. width: 600,
  2024. height: 200,
  2025. position: { my: 'left top', at: 'right top', of: $target, offset: extra_left+", 0"},
  2026. close: function(){
  2027. show_dialog.remove();
  2028. show_description.remove();
  2029. }
  2030. });
  2031. notebook_id=$(this).attr("name");
  2032. data_notebook=notebook_id.split("link");
  2033. my_glossary_id=data_notebook[1];
  2034. $.ajax({
  2035. contentType: "application/x-www-form-urlencoded",
  2036. type: "POST",
  2037. url: ajaxRequestUrl,
  2038. data: "glossary_id="+my_glossary_id,
  2039. success: function(data) {
  2040. show_description.html(data);
  2041. show_dialog.dialog("open");
  2042. }
  2043. });
  2044. });
  2045. }
  2046. });
  2047. } else {
  2048. if (type == 'manual') {
  2049. $("iframe").contents().find("body").on("click", ".glossary", function() {
  2050. is_glossary_name = $(this).html();
  2051. div_show_id="div_show_id";
  2052. div_content_id="div_content_id";
  2053. $("iframe").contents().find("body").
  2054. append('<div id="div_show_id"><div id="div_content_id">&nbsp;</div></div>');
  2055. show_dialog = $("iframe").contents().find("div#"+div_show_id);
  2056. show_description = $("iframe").contents().find("div#"+div_content_id);
  2057. var $target = $(this);
  2058. if ($("#learning_path_left_zone").is(':visible') ) {
  2059. var extra_left = $("#learning_path_left_zone").width() + 20;
  2060. } else {
  2061. var extra_left = 0;
  2062. }
  2063. //$("#"+div_show_id).dialog("destroy");
  2064. show_dialog.dialog({
  2065. autoOpen: false,
  2066. width: 600,
  2067. height: 200,
  2068. position: { my: 'left top', at: 'right top', of: $target, offset: extra_left+", 0"},
  2069. close: function(){
  2070. show_dialog.remove();
  2071. show_description.remove();
  2072. }
  2073. });
  2074. $.ajax({
  2075. contentType: "application/x-www-form-urlencoded",
  2076. type: "POST",
  2077. url: ajaxRequestUrl,
  2078. data: "glossary_name="+is_glossary_name,
  2079. success: function(data) {
  2080. show_description.html(data);
  2081. show_dialog.dialog("open");
  2082. }
  2083. });
  2084. });
  2085. }
  2086. if (type == 'fix_links') {
  2087. $(function() {
  2088. var objects = $("iframe").contents().find('object');
  2089. var pathname = location.pathname;
  2090. var coursePath = pathname.substr(0, pathname.indexOf('/main/'));
  2091. var url = "http://"+location.host + coursePath+"/courses/proxy.php?";
  2092. objects.each(function (value, obj) {
  2093. var dialogId = this.id +'_dialog';
  2094. var openerId = this.id +'_opener';
  2095. var link = '<a id="'+openerId+'" href="#" class="generated btn">'+
  2096. '<div style="text-align: center"><img src="<?php echo Display::returnIconPath('play-circle-8x.png'); ?>"/><br />If video does not work, try clicking here.</div></a>';
  2097. var embed = $("iframe").contents().find("#"+this.id).find('embed').first();
  2098. var hasHttp = embed.attr('src').indexOf("http");
  2099. if (hasHttp < 0) {
  2100. return true;
  2101. }
  2102. var height = embed.attr('height');
  2103. var width = embed.attr('width');
  2104. var src = embed.attr('src').replace('https', 'http');
  2105. var completeUrl = url + 'width='+embed.attr('width')+
  2106. '&height='+height+
  2107. '&id='+this.id+
  2108. '&flashvars='+encodeURIComponent(embed.attr('flashvars'))+
  2109. '&src='+src+
  2110. '&width='+width;
  2111. var iframe = '<iframe ' +
  2112. 'style="border: 0px;" width="100%" height="100%" ' +
  2113. 'src="'+completeUrl+
  2114. '">' +
  2115. '</iframe>';
  2116. $("iframe").contents().find("#"+this.id).append(link + '<br />');
  2117. $("iframe").contents().find('#' + openerId).click(function() {
  2118. var w = window.open(completeUrl, "Video", "width="+width+", "+"height="+height+"");
  2119. w = window.document.title = 'Video';
  2120. });
  2121. });
  2122. var iframes = $("iframe").contents().find('iframe');
  2123. iframes.each(function (value, obj) {
  2124. var randLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
  2125. var uniqid = randLetter + Date.now();
  2126. var openerId = uniqid +'_opener';
  2127. var link = '<a id="'+openerId+'" class="generated" href="#">Open website <img width="16px" src="<?php echo Display::returnIconPath('link-external.png'); ?>"/></a>';
  2128. var embed = $(this);
  2129. var height = embed.attr('height');
  2130. var width = embed.attr('width');
  2131. var src = embed.attr('src');
  2132. var completeUrl = url + 'width='+embed.attr('width')+
  2133. '&height='+height+
  2134. '&type=iframe'+
  2135. '&id='+uniqid+
  2136. '&src='+src+
  2137. '&width='+width;
  2138. var result = $("iframe").contents().find('#'+openerId);
  2139. var n = src.indexOf("youtube.com");
  2140. if (n > 0) {
  2141. return true;
  2142. }
  2143. if (result.length == 0) {
  2144. if (embed.prev().attr('class') != 'generated') {
  2145. $(this).parent().prepend(link + '<br />');
  2146. $("iframe").contents().find('#' + openerId).click(function() {
  2147. width = 1280;
  2148. height = 640;
  2149. var win = window.open(completeUrl, "Video", "width=" + width + ", " + "height=" + height + "");
  2150. win.document.title = 'Video';
  2151. });
  2152. }
  2153. }
  2154. });
  2155. var anchors = $("iframe").contents().find('a').not('.generated');
  2156. anchors.each(function (value, obj) {
  2157. if ($(this).next().attr('class') != 'generated') {
  2158. var content = $(this).html();
  2159. content = content.replace('<br />', '');
  2160. content = content.replace('<br>', '');
  2161. content = $.trim(content);
  2162. if (content == '') {
  2163. return true;
  2164. }
  2165. if ($(this).attr('href')) {
  2166. var hasLocalhost = $(this).attr('href').indexOf(location.host);
  2167. if (hasLocalhost > 0) {
  2168. return true;
  2169. }
  2170. var hasJs = $(this).attr('href').indexOf('javascript');
  2171. if (hasJs >= 0) {
  2172. return true;
  2173. }
  2174. }
  2175. if ($(this).attr('class')) {
  2176. var hasAccordion = $(this).attr('class').indexOf('accordion-toggle');
  2177. if (hasAccordion >= 0) {
  2178. return true;
  2179. }
  2180. }
  2181. var src = $(this).attr('href');
  2182. src = url+'&type=link&src='+src;
  2183. src = src.replace('https', 'http');
  2184. $(this).attr('href', src);
  2185. $(this).attr('target', '_blank');
  2186. var myAnchor = $('<a><img width="16px" src="<?php echo Display::returnIconPath('link-external.png'); ?>"/></a>').attr("href", src).attr('target', '_blank').attr('class', 'generated');
  2187. $(this).after(myAnchor);
  2188. $(this).after('-');
  2189. }
  2190. });
  2191. });
  2192. }
  2193. }
  2194. }
  2195. /**
  2196. * Updates the time bar with the new status. Prevents the need of a page refresh and flickering
  2197. * @param integer Number of completed items
  2198. * @param integer Number of items in total
  2199. * @param string Display mode (absolute 'abs' or percentage '%').Defaults to %
  2200. */
  2201. function update_time_bar(nbr_complete, nbr_total, mode)
  2202. {
  2203. logit_lms('update_progress_bar('+nbr_complete+', '+nbr_total+', '+mode+')',3);
  2204. logit_lms(
  2205. 'update_progress_bar with params: lms_lp_id= ' + olms.lms_lp_id +
  2206. ', lms_view_id= '+ olms.lms_view_id + ' lms_user_id= '+ olms.lms_user_id,
  2207. 3
  2208. );
  2209. if (mode == '') {
  2210. mode='%';
  2211. }
  2212. if (nbr_total == 0) {
  2213. nbr_total=1;
  2214. }
  2215. var percentage = (nbr_complete/nbr_total)*100;
  2216. percentage = Math.round(percentage);
  2217. var progress_bar = $("#progress_bar_value2");
  2218. progress_bar.css('width', percentage + "%");
  2219. var mytext = '';
  2220. switch(mode){
  2221. case 'abs':
  2222. mytext = nbr_complete + '/' + nbr_total;
  2223. break;
  2224. case '%':
  2225. default:
  2226. mytext = percentage + '%';
  2227. break;
  2228. }
  2229. progress_bar.html(mytext);
  2230. return true;
  2231. }
  2232. /**
  2233. * Update chronometer
  2234. */
  2235. function update_chronometer(text_hour, text_minute, text_second)
  2236. {
  2237. $("#hour").text(text_hour);
  2238. $("#minute").text(text_minute);
  2239. $("#second").text(text_second);
  2240. var timerData = {
  2241. hour: parseInt($("#hour").text()),
  2242. minute: parseInt($("#minute").text()),
  2243. second: parseInt($("#second").text())
  2244. };
  2245. /*
  2246. var timerData = {
  2247. hour: text_hour,
  2248. minute: text_minute,
  2249. second: text_second
  2250. };
  2251. */
  2252. //window.timerInterval = null;
  2253. clearInterval(window.timerInterval);
  2254. window.timerInterval = setInterval(function(){
  2255. // Seconds
  2256. timerData.second++;
  2257. if(timerData.second >= 60) {
  2258. timerData.second = 0;
  2259. timerData.minute++;
  2260. }
  2261. // Minutes
  2262. if(timerData.minute >= 60) {
  2263. timerData.minute = 0;
  2264. timerData.hour++;
  2265. }
  2266. $("#hour").text(timerData.hour < 10 ? '0' + timerData.hour : timerData.hour);
  2267. //$("#hour").text(timerData.hour);
  2268. $("#minute").text(timerData.minute < 10 ? '0' + timerData.minute : timerData.minute);
  2269. //$("#minute").text(timerData.minute);
  2270. $("#second").text(timerData.second < 10 ? '0' + timerData.second : timerData.second);
  2271. //$("#second").text(timerData.second);
  2272. }, 1000);
  2273. return true;
  2274. }