Show:

File: app/components/exp-lookit-instructions/component.js

  1. import Em from 'ember';
  2.  
  3. import layout from './template';
  4. import ExpFrameBaseComponent from '../exp-frame-base/component';
  5. import VideoRecord from '../../mixins/video-record';
  6.  
  7. let {
  8. $
  9. } = Em;
  10.  
  11. /**
  12. * @module exp-player
  13. * @submodule frames
  14. */
  15.  
  16. /**
  17. * A frame to display instructions to the user. The user's webcam may optionally be
  18. * displayed, and audio and video clips may be included in the instructions (and may be
  19. * required to be played before moving on).
  20. *
  21. * Each element of the 'blocks' parameter is rendered using {{#crossLink "Exp-text-block"}}{{/crossLink}}.
  22.  
  23. ```json
  24. "frames": {
  25. "instructions": {
  26. "kind": "exp-lookit-instructions",
  27. "blocks": [
  28. {
  29. "title": "Parent's role",
  30. "listblocks": [
  31. {
  32. "text": "Follow instructions"
  33. },
  34. {
  35. "text": "Only do each joke once"
  36. }
  37. ]
  38. },
  39. {
  40. "text": "It's important that we can see you",
  41. "image": {
  42. "alt": "Father holding child looking over his shoulder",
  43. "src": "https://s3.amazonaws.com/lookitcontents/exp-physics/OverShoulder.jpg"
  44. },
  45. "title": "Camera position"
  46. },
  47. {
  48. "text": "Here's some audio you have to play",
  49. "title": "Test",
  50. "mediaBlock": {
  51. "text": "You should hear 'Ready to go?'",
  52. "isVideo": false,
  53. "sources": [
  54. {
  55. "src": "https://s3.amazonaws.com/lookitcontents/exp-physics-final/audio/ready.mp3",
  56. "type": "audio/mp3"
  57. },
  58. {
  59. "src": "https://s3.amazonaws.com/lookitcontents/exp-physics-final/audio/ready.ogg",
  60. "type": "audio/ogg"
  61. }
  62. ],
  63. "mustPlay": true,
  64. "warningText": "Please try playing the sample audio."
  65. }
  66. },
  67. {
  68. "text": "Here's a video you don't have to play!",
  69. "title": "Test",
  70. "mediaBlock": {
  71. "text": "Look at that.",
  72. "isVideo": true,
  73. "sources": [
  74. {
  75. "src": "https://s3.amazonaws.com/lookitcontents/exp-physics-final/examples/7_control_same.mp4",
  76. "type": "video/mp4"
  77. },
  78. {
  79. "src": "https://s3.amazonaws.com/lookitcontents/exp-physics-final/examples/7_control_same.webm",
  80. "type": "video/webm"
  81. }
  82. ],
  83. "mustPlay": false
  84. }
  85. }
  86. ],
  87. "showWebcam": true,
  88. "webcamBlocks": [
  89. {
  90. "title": "Some webcam instructions",
  91. "listblocks": [
  92. {
  93. "text": "Like this!"
  94. },
  95. {
  96. "text": "Be careful your webcam does not have tape over it"
  97. }
  98. ]
  99. }
  100. ],
  101. "nextButtonText": "Next"
  102. }
  103. }
  104.  
  105. * ```
  106. * @class Exp-lookit-instructions
  107. * @extends Exp-frame-base
  108. * @extends Video-record
  109. */
  110.  
  111. export default ExpFrameBaseComponent.extend(VideoRecord, {
  112. layout: layout,
  113. type: 'exp-lookit-instructions',
  114. doUseCamera: Em.computed.alias('showWebcam'),
  115. frameSchemaProperties: {
  116.  
  117. // Note: don't display the following in the docs; they're not used because startRecordingAutomatically is
  118. // false.
  119.  
  120. /**
  121. * @property {Boolean} showWaitForRecordingMessage
  122. * @private
  123. */
  124.  
  125. /**
  126. * @property {Boolean} waitForRecordingMessage
  127. * @private
  128. */
  129.  
  130. /**
  131. * @property {Boolean} waitForRecordingMessageColor
  132. * @private
  133. */
  134.  
  135. /**
  136. * @property {Boolean} showWaitForUploadMessage
  137. * @private
  138. */
  139.  
  140. /**
  141. * @property {Boolean} waitForUploadMessage
  142. * @private
  143. */
  144.  
  145. /**
  146. * @property {String} waitForUploadMessageColor
  147. * @private
  148. */
  149.  
  150. /**
  151. * @property {String} waitForWebcamImage
  152. * @private
  153. */
  154.  
  155. /**
  156. * @property {String} waitForWebcamVideo
  157. * @private
  158. */
  159.  
  160. /**
  161. * Whether to display the user's webcam
  162. *
  163. * @property {Boolean} showWebcam
  164. * @default false
  165. */
  166. showWebcam: {
  167. type: 'boolean',
  168. description: 'Whether to display the user\'s webcam',
  169. default: false
  170. },
  171.  
  172. /**
  173. * Array of blocks for {{#crossLink "Exp-text-block"}}{{/crossLink}}, specifying text/images of instructions to display
  174. *
  175. * @property {Object[]} blocks
  176. * @param {String} title Title of this section
  177. * @param {String} text Paragraph text of this section
  178. * @param {Object[]} listblocks Object specifying bulleted points for this section. Each object is of the form:
  179. * {text: 'text of bullet point', image: {src: 'url', alt: 'alt-text'}}. Images are optional.
  180. * @param {Object} mediaBlock Object specifying audio or video clip to include (optional). mediaBlock should be of form:
  181. * {title: 'title text to show above audio', text: 'text to show below controls', warningText: 'Text to show in red if user tries to proceed but hasn't played; only used if mustPlay is true', sources: 'sources Array of {src: 'url', type: 'MIMEtype'} objects specifying audio sources', isVideo: 'boolean, whether video or audio', mustPlay: 'boolean, whether clip has to be played to proceed'}
  182. *
  183. */
  184. blocks: {
  185. type: 'array',
  186. items: {
  187. type: 'object',
  188. properties: {
  189. title: {
  190. type: 'string'
  191. },
  192. text: {
  193. type: 'string'
  194. },
  195. listblocks: {
  196. type: 'array',
  197. items: {
  198. type: 'object',
  199. properties: {
  200. text: {
  201. type: 'string'
  202. },
  203. image: {
  204. type: 'object',
  205. properties: {
  206. src: {
  207. type: 'string'
  208. },
  209. alt: {
  210. type: 'string'
  211. }
  212. }
  213. }
  214. }
  215. }
  216. },
  217. mediaBlock: {
  218. type: 'object',
  219. default: {},
  220. properties: {
  221. title: {
  222. type: 'string'
  223. },
  224. text: {
  225. type: 'string'
  226. },
  227. warningText: {
  228. type: 'string'
  229. },
  230. sources: {
  231. type: 'array',
  232. items: {
  233. type: 'object',
  234. properties: {
  235. src: {
  236. type: 'string'
  237. },
  238. type: {
  239. type: 'string'
  240. }
  241. }
  242. }
  243. },
  244. isVideo: {
  245. type: 'boolean',
  246. default: false
  247. },
  248. mustPlay: {
  249. type: 'boolean',
  250. default: false
  251. }
  252. }
  253. }
  254. }
  255. },
  256. default: []
  257. },
  258. /**
  259. * Array of objects specifying text/images of instructions to display under webcam view (if webcam is shown)
  260. *
  261. * @property {Object[]} blocks
  262. * @param {String} title Title of this section
  263. * @param {String} text Paragraph text of this section
  264. * @param {Object[]} listblocks Object specifying bulleted points for this section. Each object is of the form:
  265. * {text: 'text of bullet point', image: {src: 'url', alt: 'alt-text'}}. Images are optional.
  266. */
  267. webcamBlocks: {
  268. type: 'array',
  269. items: {
  270. type: 'object',
  271. properties: {
  272. title: {
  273. type: 'string'
  274. },
  275. text: {
  276. type: 'string'
  277. },
  278. listblocks: {
  279. type: 'array',
  280. items: {
  281. type: 'object',
  282. properties: {
  283. text: {
  284. type: 'string'
  285. },
  286. image: {
  287. type: 'object',
  288. properties: {
  289. src: {
  290. type: 'string'
  291. },
  292. alt: {
  293. type: 'string'
  294. }
  295. }
  296. }
  297. }
  298. }
  299. }
  300. }
  301. },
  302. default: []
  303. },
  304. /**
  305. * Whether to show a 'previous' button
  306. *
  307. * @property {Boolean} showPreviousButton
  308. * @default true
  309. */
  310. showPreviousButton: {
  311. type: 'boolean',
  312. default: true
  313. },
  314. /**
  315. * Text to display on the 'next frame' button
  316. *
  317. * @property {String} nextButtonText
  318. * @default 'Start the videos! \n (You\'ll have a moment to turn around.)'
  319. */
  320. nextButtonText: {
  321. type: 'string',
  322. default: 'Start the videos! \n (You\'ll have a moment to turn around.)'
  323. }
  324. },
  325. meta: {
  326. data: {
  327. type: 'object',
  328. properties: {
  329. }
  330. }
  331. },
  332.  
  333. showWarning: false,
  334.  
  335. actions: {
  336. mediaPlayed(e) {
  337. $(e.srcElement).attr('completed', true);
  338. $(e.srcElement).parent().attr('showWarning', false);
  339. },
  340. checkAudioThenNext() {
  341. if (this.shouldPreventNext()) {
  342. this.set('showWarning', true);
  343. } else {
  344. this.send('next');
  345. }
  346. }
  347. },
  348.  
  349. shouldPreventNext() {
  350. var done = true;
  351. var blocks = this.get('blocks');
  352. for (var iBlock = 0; iBlock < blocks.length; iBlock++) { // for each block
  353. if (blocks[iBlock].hasOwnProperty('mediaBlock')) { // if it has a mediaBlock
  354. // find the appropriate element
  355. var $elem = $('#media-' + iBlock + ' .player-media');
  356. if (blocks[iBlock].mediaBlock.hasOwnProperty('mustPlay') && blocks[iBlock].mediaBlock.mustPlay) { // if the mediaBlock must be played
  357. // if it's not completed
  358. if ($elem.attr('completed') != 'true') {
  359. done = false;
  360. $elem.parent().attr('showWarning', true);
  361. }
  362. } else { // does not have to be played
  363. $elem.parent().attr('showWarning', false); // Set this explicitly
  364. // so the warning isn't visible, although :not([showWarning])
  365. // selector should handle in almost all browsers
  366. }
  367. }
  368. }
  369. return !done;
  370. }
  371. });
  372.