@lookit/record 3.0.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -272,6 +272,11 @@ declare class VideoConsentPlugin implements JsPsychPlugin<Info$3> {
272
272
  };
273
273
  private readonly recorder;
274
274
  private readonly video_container_id;
275
+ private readonly msg_container_id;
276
+ private uploadingMsg;
277
+ private startingMsg;
278
+ private recordingMsg;
279
+ private notRecordingMsg;
275
280
  /**
276
281
  * Instantiate video consent plugin.
277
282
  *
@@ -305,13 +310,30 @@ declare class VideoConsentPlugin implements JsPsychPlugin<Info$3> {
305
310
  */
306
311
  private playbackFeed;
307
312
  /**
308
- * Put back the webcam feed once the video recording has ended. This is used
309
- * with the "ended" Event.
313
+ * Get message container that appears alongside the video element.
314
+ *
315
+ * @param display - HTML element for experiment.
316
+ * @returns Message container div element.
317
+ */
318
+ private getMessageContainer;
319
+ /**
320
+ * Add HTML-formatted message alongside the video feed, e.g. for waiting
321
+ * periods during webcam feed transitions (starting, stopping/uploading). This
322
+ * will also replace an existing message with the new one. To clear any
323
+ * existing messages, pass an empty string.
324
+ *
325
+ * @param display - HTML element for experiment.
326
+ * @param message - HTML content for message div.
327
+ */
328
+ private addMessage;
329
+ /**
330
+ * Put back the webcam feed once the video recording playback has ended. This
331
+ * is used with the "ended" Event.
310
332
  *
311
333
  * @param display - JsPsych display HTML element.
312
334
  * @returns Event function
313
335
  */
314
- private onEnded;
336
+ private onPlaybackEnded;
315
337
  /**
316
338
  * Retrieve button element from DOM.
317
339
  *
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import Handlebars from 'handlebars';
6
6
 
7
7
  var _package = {
8
8
  name: "@lookit/record",
9
- version: "3.0.1",
9
+ version: "4.0.0",
10
10
  description: "Recording extensions and plugins for CHS studies.",
11
11
  homepage: "https://github.com/lookit/lookit-jspsych#readme",
12
12
  bugs: {
@@ -48,7 +48,7 @@ var _package = {
48
48
  },
49
49
  peerDependencies: {
50
50
  "@lookit/data": "^0.2.0",
51
- "@lookit/templates": "^2.0.0",
51
+ "@lookit/templates": "^2.1.0",
52
52
  jspsych: "^8.0.3"
53
53
  }
54
54
  };
@@ -141,21 +141,10 @@ class CreateURLError extends Error {
141
141
  this.name = "CreateURLError";
142
142
  }
143
143
  }
144
- class VideoContainerNotFoundError extends Error {
145
- constructor() {
146
- super("Video Container could not be found.");
147
- this.name = "VideoContainerError";
148
- }
149
- }
150
- class ButtonNotFoundError extends Error {
151
- constructor(id) {
152
- super(`"${id}" button not found.`);
153
- this.name = "ButtonNotFoundError";
154
- }
155
- }
156
- class ImageNotFoundError extends Error {
157
- constructor(id) {
158
- super(`"${id}" image not found.`);
144
+ class ElementNotFoundError extends Error {
145
+ constructor(id, tag) {
146
+ super(`"${id}" ${tag} not found.`);
147
+ this.name = "ElementNotFoundError";
159
148
  }
160
149
  }
161
150
 
@@ -268,9 +257,9 @@ class Recorder {
268
257
  this.recorder.stop();
269
258
  this.stream.getTracks().map((t) => t.stop());
270
259
  }
271
- stop() {
260
+ stop(maintain_container_size = false) {
261
+ this.clearWebcamFeed(maintain_container_size);
272
262
  this.stopTracks();
273
- this.clearWebcamFeed();
274
263
  if (!this.stopPromise) {
275
264
  throw new NoStopPromiseError();
276
265
  }
@@ -315,11 +304,20 @@ class Recorder {
315
304
  link.click();
316
305
  }
317
306
  }
318
- clearWebcamFeed() {
307
+ clearWebcamFeed(maintain_container_size) {
319
308
  const webcam_feed_element = document.querySelector(
320
309
  `#${this.webcam_element_id}`
321
310
  );
322
311
  if (webcam_feed_element) {
312
+ if (maintain_container_size) {
313
+ const parent_div = webcam_feed_element.parentElement;
314
+ if (parent_div) {
315
+ const width = webcam_feed_element.offsetWidth;
316
+ const height = webcam_feed_element.offsetHeight;
317
+ parent_div.style.height = `${height}px`;
318
+ parent_div.style.width = `${width}px`;
319
+ }
320
+ }
323
321
  webcam_feed_element.remove();
324
322
  }
325
323
  }
@@ -389,6 +387,11 @@ const _VideoConsentPlugin = class {
389
387
  constructor(jsPsych) {
390
388
  this.jsPsych = jsPsych;
391
389
  this.video_container_id = "lookit-jspsych-video-container";
390
+ this.msg_container_id = "lookit-jspsych-video-msg-container";
391
+ this.uploadingMsg = null;
392
+ this.startingMsg = null;
393
+ this.recordingMsg = null;
394
+ this.notRecordingMsg = null;
392
395
  this.jsPsych = jsPsych;
393
396
  this.recorder = new Recorder(this.jsPsych);
394
397
  }
@@ -400,13 +403,25 @@ const _VideoConsentPlugin = class {
400
403
  this.stopButton(display);
401
404
  this.playButton(display);
402
405
  this.nextButton(display);
406
+ this.uploadingMsg = chsTemplates.translateString(
407
+ "exp-lookit-video-consent.Stopping-and-uploading"
408
+ );
409
+ this.startingMsg = chsTemplates.translateString(
410
+ "exp-lookit-video-consent.Starting-recorder"
411
+ );
412
+ this.recordingMsg = chsTemplates.translateString(
413
+ "exp-lookit-video-consent.Recording"
414
+ );
415
+ this.notRecordingMsg = chsTemplates.translateString(
416
+ "exp-lookit-video-consent.Not-recording"
417
+ );
403
418
  }
404
419
  getVideoContainer(display) {
405
420
  const videoContainer = display.querySelector(
406
421
  `div#${this.video_container_id}`
407
422
  );
408
423
  if (!videoContainer) {
409
- throw new VideoContainerNotFoundError();
424
+ throw new ElementNotFoundError(this.video_container_id, "div");
410
425
  }
411
426
  return videoContainer;
412
427
  }
@@ -417,14 +432,31 @@ const _VideoConsentPlugin = class {
417
432
  }
418
433
  playbackFeed(display) {
419
434
  const videoContainer = this.getVideoContainer(display);
420
- this.recorder.insertPlaybackFeed(videoContainer, this.onEnded(display));
435
+ this.recorder.insertPlaybackFeed(
436
+ videoContainer,
437
+ this.onPlaybackEnded(display)
438
+ );
421
439
  }
422
- onEnded(display) {
440
+ getMessageContainer(display) {
441
+ const msgContainer = display.querySelector(
442
+ `div#${this.msg_container_id}`
443
+ );
444
+ if (!msgContainer) {
445
+ throw new ElementNotFoundError(this.msg_container_id, "div");
446
+ }
447
+ return msgContainer;
448
+ }
449
+ addMessage(display, message) {
450
+ const msgContainer = this.getMessageContainer(display);
451
+ msgContainer.innerHTML = message;
452
+ }
453
+ onPlaybackEnded(display) {
423
454
  return () => {
424
455
  const next = this.getButton(display, "next");
425
456
  const play = this.getButton(display, "play");
426
457
  const record = this.getButton(display, "record");
427
458
  this.recordFeed(display);
459
+ this.addMessage(display, this.notRecordingMsg);
428
460
  next.disabled = false;
429
461
  play.disabled = false;
430
462
  record.disabled = false;
@@ -433,14 +465,14 @@ const _VideoConsentPlugin = class {
433
465
  getButton(display, id) {
434
466
  const btn = display.querySelector(`button#${id}`);
435
467
  if (!btn) {
436
- throw new ButtonNotFoundError(id);
468
+ throw new ElementNotFoundError(id, "button");
437
469
  }
438
470
  return btn;
439
471
  }
440
472
  getImg(display, id) {
441
473
  const img = display.querySelector(`img#${id}`);
442
474
  if (!img) {
443
- throw new ImageNotFoundError(id);
475
+ throw new ElementNotFoundError(id, "img");
444
476
  }
445
477
  return img;
446
478
  }
@@ -450,12 +482,14 @@ const _VideoConsentPlugin = class {
450
482
  const play = this.getButton(display, "play");
451
483
  const next = this.getButton(display, "next");
452
484
  record.addEventListener("click", async () => {
485
+ this.addMessage(display, this.startingMsg);
453
486
  record.disabled = true;
454
- stop.disabled = false;
455
487
  play.disabled = true;
456
488
  next.disabled = true;
457
- this.getImg(display, "record-icon").style.visibility = "visible";
458
489
  await this.recorder.start(true, _VideoConsentPlugin.info.name);
490
+ this.getImg(display, "record-icon").style.visibility = "visible";
491
+ this.addMessage(display, this.recordingMsg);
492
+ stop.disabled = false;
459
493
  });
460
494
  }
461
495
  playButton(display) {
@@ -473,11 +507,14 @@ const _VideoConsentPlugin = class {
473
507
  const play = this.getButton(display, "play");
474
508
  stop.addEventListener("click", async () => {
475
509
  stop.disabled = true;
476
- record.disabled = false;
477
- play.disabled = false;
478
- await this.recorder.stop();
510
+ this.addMessage(display, this.uploadingMsg);
511
+ await this.recorder.stop(true);
479
512
  this.recorder.reset();
480
513
  this.recordFeed(display);
514
+ this.getImg(display, "record-icon").style.visibility = "hidden";
515
+ this.addMessage(display, this.notRecordingMsg);
516
+ play.disabled = false;
517
+ record.disabled = false;
481
518
  });
482
519
  }
483
520
  nextButton(display) {