@lookit/record 3.0.1 → 4.1.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/README.md +125 -6
- package/dist/index.browser.js +136 -41
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.min.js +16 -16
- package/dist/index.browser.min.js.map +1 -1
- package/dist/index.cjs +135 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +129 -12
- package/dist/index.js +135 -40
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/consentVideo.spec.ts +38 -12
- package/src/consentVideo.ts +80 -19
- package/src/errors.ts +7 -27
- package/src/index.spec.ts +387 -12
- package/src/recorder.spec.ts +170 -6
- package/src/recorder.ts +37 -5
- package/src/start.ts +7 -1
- package/src/stop.ts +41 -7
- package/src/trial.ts +97 -11
package/dist/index.d.ts
CHANGED
|
@@ -132,6 +132,11 @@ declare const info$3: {
|
|
|
132
132
|
readonly default: false;
|
|
133
133
|
};
|
|
134
134
|
};
|
|
135
|
+
readonly data: {
|
|
136
|
+
readonly chs_type: {
|
|
137
|
+
readonly type: ParameterType.STRING;
|
|
138
|
+
};
|
|
139
|
+
};
|
|
135
140
|
};
|
|
136
141
|
type Info$3 = typeof info$3;
|
|
137
142
|
/** The video consent plugin. */
|
|
@@ -269,9 +274,19 @@ declare class VideoConsentPlugin implements JsPsychPlugin<Info$3> {
|
|
|
269
274
|
readonly default: false;
|
|
270
275
|
};
|
|
271
276
|
};
|
|
277
|
+
readonly data: {
|
|
278
|
+
readonly chs_type: {
|
|
279
|
+
readonly type: ParameterType.STRING;
|
|
280
|
+
};
|
|
281
|
+
};
|
|
272
282
|
};
|
|
273
283
|
private readonly recorder;
|
|
274
284
|
private readonly video_container_id;
|
|
285
|
+
private readonly msg_container_id;
|
|
286
|
+
private uploadingMsg;
|
|
287
|
+
private startingMsg;
|
|
288
|
+
private recordingMsg;
|
|
289
|
+
private notRecordingMsg;
|
|
275
290
|
/**
|
|
276
291
|
* Instantiate video consent plugin.
|
|
277
292
|
*
|
|
@@ -305,13 +320,30 @@ declare class VideoConsentPlugin implements JsPsychPlugin<Info$3> {
|
|
|
305
320
|
*/
|
|
306
321
|
private playbackFeed;
|
|
307
322
|
/**
|
|
308
|
-
*
|
|
309
|
-
*
|
|
323
|
+
* Get message container that appears alongside the video element.
|
|
324
|
+
*
|
|
325
|
+
* @param display - HTML element for experiment.
|
|
326
|
+
* @returns Message container div element.
|
|
327
|
+
*/
|
|
328
|
+
private getMessageContainer;
|
|
329
|
+
/**
|
|
330
|
+
* Add HTML-formatted message alongside the video feed, e.g. for waiting
|
|
331
|
+
* periods during webcam feed transitions (starting, stopping/uploading). This
|
|
332
|
+
* will also replace an existing message with the new one. To clear any
|
|
333
|
+
* existing messages, pass an empty string.
|
|
334
|
+
*
|
|
335
|
+
* @param display - HTML element for experiment.
|
|
336
|
+
* @param message - HTML content for message div.
|
|
337
|
+
*/
|
|
338
|
+
private addMessage;
|
|
339
|
+
/**
|
|
340
|
+
* Put back the webcam feed once the video recording playback has ended. This
|
|
341
|
+
* is used with the "ended" Event.
|
|
310
342
|
*
|
|
311
343
|
* @param display - JsPsych display HTML element.
|
|
312
344
|
* @returns Event function
|
|
313
345
|
*/
|
|
314
|
-
private
|
|
346
|
+
private onPlaybackEnded;
|
|
315
347
|
/**
|
|
316
348
|
* Retrieve button element from DOM.
|
|
317
349
|
*
|
|
@@ -371,7 +403,9 @@ declare class VideoConsentPlugin implements JsPsychPlugin<Info$3> {
|
|
|
371
403
|
|
|
372
404
|
declare const info$2: {
|
|
373
405
|
readonly name: "start-record-plugin";
|
|
406
|
+
readonly version: string;
|
|
374
407
|
readonly parameters: {};
|
|
408
|
+
readonly data: {};
|
|
375
409
|
};
|
|
376
410
|
type Info$2 = typeof info$2;
|
|
377
411
|
/** Start recording. Used by researchers who want to record across trials. */
|
|
@@ -379,7 +413,9 @@ declare class StartRecordPlugin implements JsPsychPlugin<Info$2> {
|
|
|
379
413
|
private jsPsych;
|
|
380
414
|
static readonly info: {
|
|
381
415
|
readonly name: "start-record-plugin";
|
|
416
|
+
readonly version: string;
|
|
382
417
|
readonly parameters: {};
|
|
418
|
+
readonly data: {};
|
|
383
419
|
};
|
|
384
420
|
private recorder;
|
|
385
421
|
/**
|
|
@@ -394,12 +430,32 @@ declare class StartRecordPlugin implements JsPsychPlugin<Info$2> {
|
|
|
394
430
|
|
|
395
431
|
declare const info$1: {
|
|
396
432
|
readonly name: "stop-record-plugin";
|
|
433
|
+
readonly version: string;
|
|
397
434
|
readonly parameters: {
|
|
435
|
+
/**
|
|
436
|
+
* This string can contain HTML markup. Any content provided will be
|
|
437
|
+
* displayed while the recording is uploading. If null (the default), then
|
|
438
|
+
* the default 'uploading video, please wait' (or appropriate translation
|
|
439
|
+
* based on 'locale') will be displayed. Use a blank string for no
|
|
440
|
+
* message/content.
|
|
441
|
+
*/
|
|
442
|
+
readonly wait_for_upload_message: {
|
|
443
|
+
readonly type: ParameterType.HTML_STRING;
|
|
444
|
+
readonly default: string | null;
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* Locale code used for translating the default 'uploading video, please
|
|
448
|
+
* wait' message. This code must be present in the translation files. If the
|
|
449
|
+
* code is not found then English will be used. If the
|
|
450
|
+
* 'wait_for_upload_message' parameter is specified then this value is
|
|
451
|
+
* ignored.
|
|
452
|
+
*/
|
|
398
453
|
readonly locale: {
|
|
399
454
|
readonly type: ParameterType.STRING;
|
|
400
455
|
readonly default: "en-us";
|
|
401
456
|
};
|
|
402
457
|
};
|
|
458
|
+
readonly data: {};
|
|
403
459
|
};
|
|
404
460
|
type Info$1 = typeof info$1;
|
|
405
461
|
/** Stop recording. Used by researchers who want to record across trials. */
|
|
@@ -407,12 +463,32 @@ declare class StopRecordPlugin implements JsPsychPlugin<Info$1> {
|
|
|
407
463
|
private jsPsych;
|
|
408
464
|
static readonly info: {
|
|
409
465
|
readonly name: "stop-record-plugin";
|
|
466
|
+
readonly version: string;
|
|
410
467
|
readonly parameters: {
|
|
468
|
+
/**
|
|
469
|
+
* This string can contain HTML markup. Any content provided will be
|
|
470
|
+
* displayed while the recording is uploading. If null (the default), then
|
|
471
|
+
* the default 'uploading video, please wait' (or appropriate translation
|
|
472
|
+
* based on 'locale') will be displayed. Use a blank string for no
|
|
473
|
+
* message/content.
|
|
474
|
+
*/
|
|
475
|
+
readonly wait_for_upload_message: {
|
|
476
|
+
readonly type: ParameterType.HTML_STRING;
|
|
477
|
+
readonly default: string | null;
|
|
478
|
+
};
|
|
479
|
+
/**
|
|
480
|
+
* Locale code used for translating the default 'uploading video, please
|
|
481
|
+
* wait' message. This code must be present in the translation files. If the
|
|
482
|
+
* code is not found then English will be used. If the
|
|
483
|
+
* 'wait_for_upload_message' parameter is specified then this value is
|
|
484
|
+
* ignored.
|
|
485
|
+
*/
|
|
411
486
|
readonly locale: {
|
|
412
487
|
readonly type: ParameterType.STRING;
|
|
413
488
|
readonly default: "en-us";
|
|
414
489
|
};
|
|
415
490
|
};
|
|
491
|
+
readonly data: {};
|
|
416
492
|
};
|
|
417
493
|
private recorder;
|
|
418
494
|
/**
|
|
@@ -432,12 +508,39 @@ declare class StopRecordPlugin implements JsPsychPlugin<Info$1> {
|
|
|
432
508
|
trial(display_element: HTMLElement, trial: TrialType<Info$1>): void;
|
|
433
509
|
}
|
|
434
510
|
|
|
435
|
-
|
|
511
|
+
interface Parameters {
|
|
512
|
+
/**
|
|
513
|
+
* Content that should be displayed while the recording is uploading. If null
|
|
514
|
+
* (the default), then the default 'uploading video, please wait...' (or
|
|
515
|
+
* appropriate translation based on 'locale') will be displayed. Use a blank
|
|
516
|
+
* string for no message/content. Otherwise this parameter can be set to a
|
|
517
|
+
* custom string and can contain HTML markup. If you want to embed
|
|
518
|
+
* images/video/audio in this HTML string, be sure to preload the media files
|
|
519
|
+
* with the `preload` plugin and manual preloading. Use a blank string (`""`)
|
|
520
|
+
* for no message/content.
|
|
521
|
+
*
|
|
522
|
+
* @default null
|
|
523
|
+
*/
|
|
524
|
+
wait_for_upload_message?: null | string;
|
|
525
|
+
/**
|
|
526
|
+
* Locale code used for translating the default 'uploading video, please
|
|
527
|
+
* wait...' message. This code must be present in the translation files. If
|
|
528
|
+
* the code is not found then English will be used. If the
|
|
529
|
+
* 'wait_for_upload_message' parameter is specified then this value
|
|
530
|
+
* isignored.
|
|
531
|
+
*
|
|
532
|
+
* @default "en-us"
|
|
533
|
+
*/
|
|
534
|
+
locale?: string;
|
|
535
|
+
}
|
|
536
|
+
/** This extension allows researchers to record webcam audio/video during trials. */
|
|
436
537
|
declare class TrialRecordExtension implements JsPsychExtension {
|
|
437
538
|
private jsPsych;
|
|
438
539
|
static readonly info: JsPsychExtensionInfo;
|
|
439
540
|
private recorder?;
|
|
440
541
|
private pluginName;
|
|
542
|
+
private uploadMsg;
|
|
543
|
+
private locale;
|
|
441
544
|
/**
|
|
442
545
|
* Video recording extension.
|
|
443
546
|
*
|
|
@@ -445,20 +548,34 @@ declare class TrialRecordExtension implements JsPsychExtension {
|
|
|
445
548
|
*/
|
|
446
549
|
constructor(jsPsych: JsPsych);
|
|
447
550
|
/**
|
|
448
|
-
*
|
|
551
|
+
* Runs on the initialize step for extensions, called when an instance of
|
|
449
552
|
* jsPsych is first initialized through initJsPsych().
|
|
553
|
+
*
|
|
554
|
+
* @param params - Parameters object
|
|
555
|
+
* @param params.wait_for_upload_message - Message to display while waiting
|
|
556
|
+
* for upload. String or null (default)
|
|
557
|
+
* @param params.locale - Message to display while waiting for upload. String
|
|
558
|
+
* or null (default).
|
|
559
|
+
*/
|
|
560
|
+
initialize(params?: Parameters): Promise<void>;
|
|
561
|
+
/**
|
|
562
|
+
* Runs at the start of a trial.
|
|
563
|
+
*
|
|
564
|
+
* @param startParams - Parameters object
|
|
565
|
+
* @param startParams.wait_for_upload_message - Message to display while
|
|
566
|
+
* waiting for upload. String or null (default). If given, this will
|
|
567
|
+
* overwrite the value used during initialization.
|
|
450
568
|
*/
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
on_start(): void;
|
|
454
|
-
/** Ran when the trial has loaded. */
|
|
569
|
+
on_start(startParams?: Parameters): void;
|
|
570
|
+
/** Runs when the trial has loaded. */
|
|
455
571
|
on_load(): void;
|
|
456
572
|
/**
|
|
457
|
-
*
|
|
573
|
+
* Runs when trial has finished.
|
|
458
574
|
*
|
|
459
|
-
* @returns
|
|
575
|
+
* @returns Any data from the trial extension that should be added to the rest
|
|
576
|
+
* of the trial data.
|
|
460
577
|
*/
|
|
461
|
-
on_finish(): {}
|
|
578
|
+
on_finish(): Promise<{}>;
|
|
462
579
|
/**
|
|
463
580
|
* Gets the plugin name for the trial that is being extended. This is same as
|
|
464
581
|
* the "trial_type" value that is stored in the data for this trial.
|
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: "
|
|
9
|
+
version: "4.1.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.
|
|
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
|
|
145
|
-
constructor() {
|
|
146
|
-
super("
|
|
147
|
-
this.name = "
|
|
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
|
}
|
|
@@ -298,6 +287,7 @@ class Recorder {
|
|
|
298
287
|
} else {
|
|
299
288
|
await this.s3.completeUpload();
|
|
300
289
|
}
|
|
290
|
+
this.reset();
|
|
301
291
|
resolve();
|
|
302
292
|
};
|
|
303
293
|
}
|
|
@@ -315,11 +305,20 @@ class Recorder {
|
|
|
315
305
|
link.click();
|
|
316
306
|
}
|
|
317
307
|
}
|
|
318
|
-
clearWebcamFeed() {
|
|
308
|
+
clearWebcamFeed(maintain_container_size) {
|
|
319
309
|
const webcam_feed_element = document.querySelector(
|
|
320
310
|
`#${this.webcam_element_id}`
|
|
321
311
|
);
|
|
322
312
|
if (webcam_feed_element) {
|
|
313
|
+
if (maintain_container_size) {
|
|
314
|
+
const parent_div = webcam_feed_element.parentElement;
|
|
315
|
+
if (parent_div) {
|
|
316
|
+
const width = webcam_feed_element.offsetWidth;
|
|
317
|
+
const height = webcam_feed_element.offsetHeight;
|
|
318
|
+
parent_div.style.height = `${height}px`;
|
|
319
|
+
parent_div.style.width = `${width}px`;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
323
322
|
webcam_feed_element.remove();
|
|
324
323
|
}
|
|
325
324
|
}
|
|
@@ -383,12 +382,22 @@ const info$3 = {
|
|
|
383
382
|
prompt_only_adults: { type: ParameterType.BOOL, default: false },
|
|
384
383
|
consent_statement_text: { type: ParameterType.STRING, default: "" },
|
|
385
384
|
omit_injury_phrase: { type: ParameterType.BOOL, default: false }
|
|
385
|
+
},
|
|
386
|
+
data: {
|
|
387
|
+
chs_type: {
|
|
388
|
+
type: ParameterType.STRING
|
|
389
|
+
}
|
|
386
390
|
}
|
|
387
391
|
};
|
|
388
392
|
const _VideoConsentPlugin = class {
|
|
389
393
|
constructor(jsPsych) {
|
|
390
394
|
this.jsPsych = jsPsych;
|
|
391
395
|
this.video_container_id = "lookit-jspsych-video-container";
|
|
396
|
+
this.msg_container_id = "lookit-jspsych-video-msg-container";
|
|
397
|
+
this.uploadingMsg = null;
|
|
398
|
+
this.startingMsg = null;
|
|
399
|
+
this.recordingMsg = null;
|
|
400
|
+
this.notRecordingMsg = null;
|
|
392
401
|
this.jsPsych = jsPsych;
|
|
393
402
|
this.recorder = new Recorder(this.jsPsych);
|
|
394
403
|
}
|
|
@@ -400,13 +409,25 @@ const _VideoConsentPlugin = class {
|
|
|
400
409
|
this.stopButton(display);
|
|
401
410
|
this.playButton(display);
|
|
402
411
|
this.nextButton(display);
|
|
412
|
+
this.uploadingMsg = chsTemplates.translateString(
|
|
413
|
+
"exp-lookit-video-consent.Stopping-and-uploading"
|
|
414
|
+
);
|
|
415
|
+
this.startingMsg = chsTemplates.translateString(
|
|
416
|
+
"exp-lookit-video-consent.Starting-recorder"
|
|
417
|
+
);
|
|
418
|
+
this.recordingMsg = chsTemplates.translateString(
|
|
419
|
+
"exp-lookit-video-consent.Recording"
|
|
420
|
+
);
|
|
421
|
+
this.notRecordingMsg = chsTemplates.translateString(
|
|
422
|
+
"exp-lookit-video-consent.Not-recording"
|
|
423
|
+
);
|
|
403
424
|
}
|
|
404
425
|
getVideoContainer(display) {
|
|
405
426
|
const videoContainer = display.querySelector(
|
|
406
427
|
`div#${this.video_container_id}`
|
|
407
428
|
);
|
|
408
429
|
if (!videoContainer) {
|
|
409
|
-
throw new
|
|
430
|
+
throw new ElementNotFoundError(this.video_container_id, "div");
|
|
410
431
|
}
|
|
411
432
|
return videoContainer;
|
|
412
433
|
}
|
|
@@ -417,14 +438,31 @@ const _VideoConsentPlugin = class {
|
|
|
417
438
|
}
|
|
418
439
|
playbackFeed(display) {
|
|
419
440
|
const videoContainer = this.getVideoContainer(display);
|
|
420
|
-
this.recorder.insertPlaybackFeed(
|
|
441
|
+
this.recorder.insertPlaybackFeed(
|
|
442
|
+
videoContainer,
|
|
443
|
+
this.onPlaybackEnded(display)
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
getMessageContainer(display) {
|
|
447
|
+
const msgContainer = display.querySelector(
|
|
448
|
+
`div#${this.msg_container_id}`
|
|
449
|
+
);
|
|
450
|
+
if (!msgContainer) {
|
|
451
|
+
throw new ElementNotFoundError(this.msg_container_id, "div");
|
|
452
|
+
}
|
|
453
|
+
return msgContainer;
|
|
454
|
+
}
|
|
455
|
+
addMessage(display, message) {
|
|
456
|
+
const msgContainer = this.getMessageContainer(display);
|
|
457
|
+
msgContainer.innerHTML = message;
|
|
421
458
|
}
|
|
422
|
-
|
|
459
|
+
onPlaybackEnded(display) {
|
|
423
460
|
return () => {
|
|
424
461
|
const next = this.getButton(display, "next");
|
|
425
462
|
const play = this.getButton(display, "play");
|
|
426
463
|
const record = this.getButton(display, "record");
|
|
427
464
|
this.recordFeed(display);
|
|
465
|
+
this.addMessage(display, this.notRecordingMsg);
|
|
428
466
|
next.disabled = false;
|
|
429
467
|
play.disabled = false;
|
|
430
468
|
record.disabled = false;
|
|
@@ -433,14 +471,14 @@ const _VideoConsentPlugin = class {
|
|
|
433
471
|
getButton(display, id) {
|
|
434
472
|
const btn = display.querySelector(`button#${id}`);
|
|
435
473
|
if (!btn) {
|
|
436
|
-
throw new
|
|
474
|
+
throw new ElementNotFoundError(id, "button");
|
|
437
475
|
}
|
|
438
476
|
return btn;
|
|
439
477
|
}
|
|
440
478
|
getImg(display, id) {
|
|
441
479
|
const img = display.querySelector(`img#${id}`);
|
|
442
480
|
if (!img) {
|
|
443
|
-
throw new
|
|
481
|
+
throw new ElementNotFoundError(id, "img");
|
|
444
482
|
}
|
|
445
483
|
return img;
|
|
446
484
|
}
|
|
@@ -450,12 +488,14 @@ const _VideoConsentPlugin = class {
|
|
|
450
488
|
const play = this.getButton(display, "play");
|
|
451
489
|
const next = this.getButton(display, "next");
|
|
452
490
|
record.addEventListener("click", async () => {
|
|
491
|
+
this.addMessage(display, this.startingMsg);
|
|
453
492
|
record.disabled = true;
|
|
454
|
-
stop.disabled = false;
|
|
455
493
|
play.disabled = true;
|
|
456
494
|
next.disabled = true;
|
|
457
|
-
this.getImg(display, "record-icon").style.visibility = "visible";
|
|
458
495
|
await this.recorder.start(true, _VideoConsentPlugin.info.name);
|
|
496
|
+
this.getImg(display, "record-icon").style.visibility = "visible";
|
|
497
|
+
this.addMessage(display, this.recordingMsg);
|
|
498
|
+
stop.disabled = false;
|
|
459
499
|
});
|
|
460
500
|
}
|
|
461
501
|
playButton(display) {
|
|
@@ -473,11 +513,13 @@ const _VideoConsentPlugin = class {
|
|
|
473
513
|
const play = this.getButton(display, "play");
|
|
474
514
|
stop.addEventListener("click", async () => {
|
|
475
515
|
stop.disabled = true;
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
await this.recorder.stop();
|
|
479
|
-
this.recorder.reset();
|
|
516
|
+
this.addMessage(display, this.uploadingMsg);
|
|
517
|
+
await this.recorder.stop(true);
|
|
480
518
|
this.recordFeed(display);
|
|
519
|
+
this.getImg(display, "record-icon").style.visibility = "hidden";
|
|
520
|
+
this.addMessage(display, this.notRecordingMsg);
|
|
521
|
+
play.disabled = false;
|
|
522
|
+
record.disabled = false;
|
|
481
523
|
});
|
|
482
524
|
}
|
|
483
525
|
nextButton(display) {
|
|
@@ -497,7 +539,12 @@ const _VideoConsentPlugin = class {
|
|
|
497
539
|
let VideoConsentPlugin = _VideoConsentPlugin;
|
|
498
540
|
VideoConsentPlugin.info = info$3;
|
|
499
541
|
|
|
500
|
-
const info$2 = {
|
|
542
|
+
const info$2 = {
|
|
543
|
+
name: "start-record-plugin",
|
|
544
|
+
version: _package.version,
|
|
545
|
+
parameters: {},
|
|
546
|
+
data: {}
|
|
547
|
+
};
|
|
501
548
|
const _StartRecordPlugin = class {
|
|
502
549
|
constructor(jsPsych) {
|
|
503
550
|
this.jsPsych = jsPsych;
|
|
@@ -519,9 +566,18 @@ StartRecordPlugin.info = info$2;
|
|
|
519
566
|
|
|
520
567
|
const info$1 = {
|
|
521
568
|
name: "stop-record-plugin",
|
|
569
|
+
version: _package.version,
|
|
522
570
|
parameters: {
|
|
523
|
-
|
|
524
|
-
|
|
571
|
+
wait_for_upload_message: {
|
|
572
|
+
type: ParameterType.HTML_STRING,
|
|
573
|
+
default: null
|
|
574
|
+
},
|
|
575
|
+
locale: {
|
|
576
|
+
type: ParameterType.STRING,
|
|
577
|
+
default: "en-us"
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
data: {}
|
|
525
581
|
};
|
|
526
582
|
class StopRecordPlugin {
|
|
527
583
|
constructor(jsPsych) {
|
|
@@ -533,11 +589,17 @@ class StopRecordPlugin {
|
|
|
533
589
|
}
|
|
534
590
|
}
|
|
535
591
|
trial(display_element, trial) {
|
|
536
|
-
|
|
592
|
+
if (trial.wait_for_upload_message == null) {
|
|
593
|
+
display_element.innerHTML = chsTemplates.uploadingVideo(trial);
|
|
594
|
+
} else {
|
|
595
|
+
display_element.innerHTML = trial.wait_for_upload_message;
|
|
596
|
+
}
|
|
537
597
|
this.recorder.stop().then(() => {
|
|
538
598
|
window.chs.sessionRecorder = null;
|
|
539
599
|
display_element.innerHTML = "";
|
|
540
600
|
this.jsPsych.finishTrial();
|
|
601
|
+
}).catch((err) => {
|
|
602
|
+
console.error("StopRecordPlugin: recorder stop/upload failed.", err);
|
|
541
603
|
});
|
|
542
604
|
}
|
|
543
605
|
}
|
|
@@ -546,19 +608,50 @@ StopRecordPlugin.info = info$1;
|
|
|
546
608
|
class TrialRecordExtension {
|
|
547
609
|
constructor(jsPsych) {
|
|
548
610
|
this.jsPsych = jsPsych;
|
|
611
|
+
this.uploadMsg = null;
|
|
612
|
+
this.locale = "en-us";
|
|
549
613
|
autoBind(this);
|
|
550
614
|
}
|
|
551
|
-
async initialize() {
|
|
615
|
+
async initialize(params) {
|
|
616
|
+
await new Promise((resolve) => {
|
|
617
|
+
this.uploadMsg = params?.wait_for_upload_message ? params.wait_for_upload_message : null;
|
|
618
|
+
this.locale = params?.locale ? params.locale : "en-us";
|
|
619
|
+
console.log(this.uploadMsg);
|
|
620
|
+
console.log(this.locale);
|
|
621
|
+
resolve();
|
|
622
|
+
});
|
|
552
623
|
}
|
|
553
|
-
on_start() {
|
|
624
|
+
on_start(startParams) {
|
|
625
|
+
if (startParams?.wait_for_upload_message) {
|
|
626
|
+
this.uploadMsg = startParams.wait_for_upload_message;
|
|
627
|
+
}
|
|
628
|
+
if (startParams?.locale) {
|
|
629
|
+
this.locale = startParams.locale;
|
|
630
|
+
}
|
|
631
|
+
console.log(this.uploadMsg);
|
|
632
|
+
console.log(this.locale);
|
|
554
633
|
this.recorder = new Recorder(this.jsPsych);
|
|
555
634
|
}
|
|
556
635
|
on_load() {
|
|
557
636
|
this.pluginName = this.getCurrentPluginName();
|
|
558
637
|
this.recorder?.start(false, `${this.pluginName}`);
|
|
559
638
|
}
|
|
560
|
-
on_finish() {
|
|
561
|
-
this.
|
|
639
|
+
async on_finish() {
|
|
640
|
+
const displayEl = this.jsPsych.getDisplayElement();
|
|
641
|
+
if (this.uploadMsg == null) {
|
|
642
|
+
displayEl.innerHTML = chsTemplates.uploadingVideo({
|
|
643
|
+
type: this.jsPsych.getCurrentTrial().type,
|
|
644
|
+
locale: this.locale
|
|
645
|
+
});
|
|
646
|
+
} else {
|
|
647
|
+
displayEl.innerHTML = this.uploadMsg;
|
|
648
|
+
}
|
|
649
|
+
try {
|
|
650
|
+
await this.recorder?.stop();
|
|
651
|
+
displayEl.innerHTML = "";
|
|
652
|
+
} catch (err) {
|
|
653
|
+
console.error("TrialRecordExtension: recorder stop/upload failed.", err);
|
|
654
|
+
}
|
|
562
655
|
return {};
|
|
563
656
|
}
|
|
564
657
|
getCurrentPluginName() {
|
|
@@ -567,7 +660,9 @@ class TrialRecordExtension {
|
|
|
567
660
|
}
|
|
568
661
|
}
|
|
569
662
|
TrialRecordExtension.info = {
|
|
570
|
-
name: "chs-trial-record-extension"
|
|
663
|
+
name: "chs-trial-record-extension",
|
|
664
|
+
version: _package.version,
|
|
665
|
+
data: {}
|
|
571
666
|
};
|
|
572
667
|
|
|
573
668
|
var img$6 = "data:image/png;base64,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";
|