lesson.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. "use strict";
  2. // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under
  3. // Secretary of Defense (Personnel & Readiness).
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the License
  11. // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12. // or implied. See the License for the specific language governing permissions and limitations under
  13. // the License.
  14. /// vwf/view/lesson creates a view interface for instruction text.
  15. ///
  16. /// @module vwf/view/lesson
  17. /// @requires vwf/view
  18. define( [ "module", "vwf/view", "jquery", "jquery-ui" ], function( module, view, $ ) {
  19. return view.load( module, {
  20. // == Module Definition ====================================================================
  21. initialize: function() {
  22. var self = this;
  23. this.lessonSteps = {};
  24. this.progressWidth = 10;
  25. this.currentTaskName = undefined;
  26. // Add CSS files
  27. var lessonCss = document.createElement('link');
  28. lessonCss.rel = 'stylesheet';
  29. lessonCss.type = 'text/css';
  30. lessonCss.href = 'vwf/view/lesson/jquery-ui-1.10.4.custom.min.css';
  31. $('head').append(lessonCss);
  32. lessonCss = document.createElement('link');
  33. lessonCss.rel = 'stylesheet';
  34. lessonCss.type = 'text/css';
  35. lessonCss.href = 'vwf/view/lesson/lesson.css';
  36. $('head').append(lessonCss);
  37. // Create instruction panel
  38. var instructionPanelDiv = document.createElement('div');
  39. instructionPanelDiv.className = 'lesson';
  40. instructionPanelDiv.id = 'instructionPanel';
  41. // Create instruction accordion
  42. var accordionDiv = document.createElement('div');
  43. accordionDiv.className = 'lesson';
  44. accordionDiv.id = 'accordion';
  45. // Create lesson progress bar
  46. var progressDiv = document.createElement('div');
  47. progressDiv.className = 'lesson';
  48. progressDiv.id = 'progress';
  49. var innerProgressDiv = document.createElement('div');
  50. innerProgressDiv.className = 'lesson progress';
  51. var innerProgressBarDiv = document.createElement('div');
  52. innerProgressBarDiv.className = 'lesson bar';
  53. innerProgressBarDiv.id = 'lessonProgressBar';
  54. $(innerProgressDiv).append(innerProgressBarDiv);
  55. $(progressDiv).append(innerProgressDiv);
  56. // Create navigation buttons
  57. var navigationDiv = document.createElement('div');
  58. navigationDiv.className = 'lesson';
  59. navigationDiv.id = 'navigation';
  60. var buttonList = document.createElement('ul');
  61. buttonList.className = 'lesson';
  62. var messageListItem = document.createElement('li');
  63. messageListItem.className = 'lesson';
  64. messageListItem.id = 'message';
  65. var messageListItemLabel = document.createElement('label');
  66. messageListItemLabel.className = 'lesson buttonLabel';
  67. $(messageListItem).append(messageListItemLabel);
  68. var startButtonListItem = document.createElement('li');
  69. startButtonListItem.className = 'lesson';
  70. startButtonListItem.id = 'startButton';
  71. var startButtonItemButton = document.createElement('button');
  72. startButtonItemButton.type = 'button';
  73. startButtonItemButton.className = 'lesson btn btn-info';
  74. startButtonItemButton.onclick = function () {
  75. startLesson.call(self);
  76. };
  77. var startButtonItemLabel = document.createElement('label');
  78. startButtonItemLabel.className = 'lesson buttonLabel';
  79. startButtonItemLabel.innerHTML = 'Start';
  80. $(startButtonItemButton).append(startButtonItemLabel);
  81. $(startButtonListItem).append(startButtonItemButton);
  82. // TODO: Implement previous method
  83. // var previousButtonListItem = document.createElement('li');
  84. // previousButtonListItem.id = 'previousButton';
  85. // var previousButtonItemButton = document.createElement('button');
  86. // previousButtonItemButton.type = 'button';
  87. // previousButtonItemButton.className = 'btn btn-info';
  88. // previousButtonItemButton.onclick = function () {
  89. // previousTask.call(self);
  90. // };
  91. // var previousButtonItemLabel = document.createElement('label');
  92. // previousButtonItemLabel.className = 'buttonLabel';
  93. // previousButtonItemLabel.innerHTML = 'Previous';
  94. // $(previousButtonItemButton).append(previousButtonItemLabel);
  95. // $(previousButtonListItem).append(previousButtonItemButton);
  96. var nextButtonListItem = document.createElement('li');
  97. nextButtonListItem.className = 'lesson';
  98. nextButtonListItem.id = 'nextButton';
  99. var nextButtonItemButton = document.createElement('button');
  100. nextButtonItemButton.type = 'button';
  101. nextButtonItemButton.className = 'lesson btn btn-info';
  102. nextButtonItemButton.onclick = function () {
  103. nextTask.call(self);
  104. };
  105. var nextButtonItemLabel = document.createElement('label');
  106. nextButtonItemLabel.className = 'lesson buttonLabel';
  107. nextButtonItemLabel.innerHTML = 'Next';
  108. $(nextButtonItemButton).append(nextButtonItemLabel);
  109. $(nextButtonListItem).append(nextButtonItemButton);
  110. var completeButtonListItem = document.createElement('li');
  111. completeButtonListItem.className = 'lesson';
  112. completeButtonListItem.id = 'completeButton';
  113. var completeButtonItemButton = document.createElement('button');
  114. completeButtonItemButton.type = 'button';
  115. completeButtonItemButton.className = 'lesson btn btn-info';
  116. completeButtonItemButton.onclick = function () {
  117. completeLesson.call(self);
  118. };
  119. var completeButtonItemLabel = document.createElement('label');
  120. completeButtonItemLabel.className = 'lesson buttonLabel';
  121. completeButtonItemLabel.innerHTML = 'Complete';
  122. $(completeButtonItemButton).append(completeButtonItemLabel);
  123. $(completeButtonListItem).append(completeButtonItemButton);
  124. $(buttonList).append(messageListItem);
  125. $(buttonList).append(startButtonListItem);
  126. // $(buttonList).append(previousButtonListItem);
  127. $(buttonList).append(nextButtonListItem);
  128. $(buttonList).append(completeButtonListItem);
  129. $(navigationDiv).append(buttonList);
  130. $(instructionPanelDiv).append(accordionDiv);
  131. $(instructionPanelDiv).append(progressDiv);
  132. $(instructionPanelDiv).append(navigationDiv);
  133. $('body').append(instructionPanelDiv);
  134. },
  135. createdProperty: function( nodeId, propertyName, propertyValue ) {
  136. return this.satProperty( nodeId, propertyName, propertyValue );
  137. },
  138. initializedProperty: function (nodeId, propertyName, propertyValue) {
  139. return this.satProperty( nodeId, propertyName, propertyValue );
  140. },
  141. satProperty: function( nodeId, propertyName, propertyValue ) {
  142. switch ( propertyName ) {
  143. case "status":
  144. var status = propertyValue;
  145. if ( nodeId === vwf_view.kernel.find( '', '/lesson' )[ 0 ] ) {
  146. switch ( status ) {
  147. case "entered":
  148. this.currentTaskName = vwf_view.kernel.name( nodeId );
  149. this.progressWidth = 10;
  150. $( '#lessonProgressBar' ).css( 'display', 'block' );
  151. $( '#lessonProgressBar' ).css( 'width', '10px' );
  152. $( '#message' ).css( 'display', 'none' );
  153. $( '#startButton' ).css( 'display', 'none' );
  154. $( '#nextButton' ).css( 'display', 'inline-block' );
  155. $( 'a' ).css( 'color', 'white' );
  156. if ( $( '#accordion' ).html() == '' ) {
  157. updateLessonInstructions.call( self, this.lessonSteps );
  158. }
  159. break;
  160. case "completed":
  161. $('#lessonProgressBar').css('width', '100%');
  162. $('#nextButton').css('display', 'none');
  163. $('#completeButton').css('display', 'inline-block');
  164. break;
  165. case "inactive":
  166. $( '#lessonProgressBar' ).css( 'display', 'none' );
  167. $( '#completeButton' ).css( 'display', 'none' );
  168. $( '#message' ).css( 'display', 'inline-block' );
  169. $( '#startButton' ).css( 'display', 'inline-block' );
  170. break;
  171. }
  172. } else {
  173. var stepDivId = nodeId.replace( /\:/g, "_" ).replace( /\./g, "-" ).replace(/\//g, "_");
  174. switch ( status ) {
  175. case "entered":
  176. this.currentTaskName = vwf_view.kernel.name( nodeId );
  177. var $stepDiv = $( "#" + stepDivId );
  178. if ( $stepDiv.length ) {
  179. var $accordion = $stepDiv.parent().parent();
  180. if ( $accordion.length ) {
  181. $accordion.accordion( "option", "active",
  182. Number( $stepDiv.attr( "data-index" ) ) );
  183. }
  184. }
  185. break;
  186. case "completed":
  187. if ( $( '#div--' + stepDivId ) ) {
  188. $( '#' + stepDivId ).css( 'color', 'green' );
  189. }
  190. var numTasks = 0;
  191. for ( var step in this.lessonSteps ) {
  192. numTasks++;
  193. }
  194. var widthDelta = Math.ceil( 100 / numTasks );
  195. var pixelWidth = $( '#progress' ).css( 'width' );
  196. pixelWidth = pixelWidth.substring( 0, pixelWidth.length - 2 );
  197. this.progressWidth = this.progressWidth +
  198. ( pixelWidth * widthDelta * 0.01 );
  199. $( '#lessonProgressBar' ).css( 'width', this.progressWidth + 'px' );
  200. break;
  201. case "inactive":
  202. var $accordion = $( '#accordion--' + stepDivId );
  203. if ( $accordion.length ) {
  204. $accordion.accordion( "option", "active", false );
  205. }
  206. break;
  207. }
  208. }
  209. break;
  210. case "text":
  211. if ( propertyValue ) {
  212. this.lessonSteps[ nodeId ] = propertyValue;
  213. }
  214. break;
  215. }
  216. },
  217. } );
  218. // -- updateLessonInstructions ----------------------------------------------------------
  219. function updateLessonInstructions( lessonSteps )
  220. {
  221. var lessonID = vwf_view.kernel.find('', '/lesson')[ 0 ];
  222. var stepIds = vwf_view.kernel.find( lessonID, "./*" );
  223. var $accordion = $( "#accordion" );
  224. for ( var i = 0; i < stepIds.length; i++ ) {
  225. var step = stepIds[ i ];
  226. var stepText = lessonSteps[ step ];
  227. var stepSafeId = step.replace(/\:/g, "_").replace(/\./g, "-").replace(/\//g, "_");
  228. var $subAccordionDiv = [];
  229. if ( stepText ) {
  230. $subAccordionDiv = $( "<div/>", {
  231. id: "accordion--" + stepSafeId,
  232. "data-index": i
  233. } );
  234. $accordion.append( "<p class='lesson taskTitle'>" + stepText + "</p>" );
  235. $accordion.append( $subAccordionDiv );
  236. $accordion.append( "<br />" );
  237. }
  238. var substepIds = vwf_view.kernel.find( step, "./*" );
  239. for ( var j = 0; j < substepIds.length; j++ ) {
  240. var substep = substepIds[ j ];
  241. var substepText = lessonSteps[ substep ];
  242. if ( substepText ) {
  243. var substepSafeId = substep.replace(/\:/g, "_").replace(/\./g, "-").replace(/\//g, "_");
  244. $subAccordionDiv.append( [
  245. "<h2>",
  246. " <a id='" + substepSafeId + "' data-index='" + j + "' href='#'>" + substepText + "</a>",
  247. "</h2>"
  248. ].join( "\n" ) );
  249. $subAccordionDiv.append( "<div id='div--" + substepSafeId + "'></div>");
  250. }
  251. vwf_view.kernel.find( substep, "./*", function( subsubstep ) {
  252. processSubSubSteps( substep, subsubstep );
  253. } );
  254. }
  255. }
  256. $accordion.children('div').accordion({ active: false, collapsible: true });
  257. function processSubSubSteps( parentStepID, childStepID ) {
  258. var text = lessonSteps[childStepID];
  259. if ( text ) {
  260. var htmlParent = parentStepID.replace(/\:/g, "_").replace(/\./g, "-").replace(/\//g, "_");
  261. while(! $('#div--' + htmlParent).length)
  262. {
  263. htmlParent = htmlParent.substring(0, htmlParent.lastIndexOf('_'));
  264. }
  265. if( $('#div--' + htmlParent).html() != "" ) $('#div--' + htmlParent).append("<br />");
  266. $('#div--' + htmlParent).append(text + "<br />");
  267. }
  268. vwf_view.kernel.find( childStepID, "./*", function( childSubStepID ) {
  269. processSubSubSteps( childStepID, childSubStepID );
  270. } );
  271. };
  272. }
  273. // -- startLesson -----------------------------------------------------------------------
  274. function startLesson()
  275. {
  276. vwf_view.kernel.callMethod(vwf_view.kernel.find('','/lesson')[0], 'enter', []);
  277. }
  278. // -- nextTask --------------------------------------------------------------------------
  279. function nextTask()
  280. {
  281. vwf_view.kernel.callMethod(vwf_view.kernel.find('','//'+this.currentTaskName)[0], 'next', []);
  282. }
  283. // -- completeLesson --------------------------------------------------------------------
  284. function completeLesson()
  285. {
  286. vwf_view.kernel.callMethod(vwf_view.kernel.find('','/lesson')[0], 'exit', []);
  287. }
  288. } );