mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-10 19:20:55 +00:00
Merge branch 'master' into respond-while-playing
This commit is contained in:
commit
dbb001c0c7
@ -76,10 +76,18 @@
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
/* only apply the hover style on devices with a mouse/pointer that can hover - issue #977 */
|
||||
@media (hover: hover) {
|
||||
.jspsych-btn:hover {
|
||||
background-color: #ddd;
|
||||
border-color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
.jspsych-btn:active {
|
||||
background-color: #ddd;
|
||||
border-color:#000000;
|
||||
}
|
||||
|
||||
.jspsych-btn:disabled {
|
||||
background-color: #eee;
|
||||
|
@ -8,7 +8,7 @@ Parameters with a default value of *undefined* must be specified. Other paramete
|
||||
|
||||
Parameter | Type | Default Value | Description
|
||||
----------|------|---------------|------------
|
||||
sources | array | *undefined* | An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the [cross-browser compatibility](https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats). Usually .mp4 is a safe cross-browser option. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference.
|
||||
sources | array | *undefined* | An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the [cross-browser compatibility](https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats). Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference.
|
||||
choices | array of strings | [] | Labels for the buttons. Each different string in the array will generate a different button.
|
||||
button_html | HTML string | `'<button class="jspsych-btn">%choice%</button>'` | A template of HTML for generating the button elements. You can override this to create customized buttons of various kinds. The string `%choice%` will be changed to the corresponding element of the `choices` array. You may also specify an array of strings, if you need different HTML to render for each button. If you do specify an array, the `choices` array and this array must have the same length. The HTML from position 0 in the `button_html` array will be used to create the button for element 0 in the `choices` array, and so on.
|
||||
margin_vertical | string | '0px' | Vertical margin of the button(s).
|
||||
|
@ -8,7 +8,7 @@ Parameters with a default value of *undefined* must be specified. Other paramete
|
||||
|
||||
Parameter | Type | Default Value | Description
|
||||
----------|------|---------------|------------
|
||||
sources | array | *undefined* | An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the [cross-browser compatibility](https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats). Usually .mp4 is a safe cross-browser option. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference.
|
||||
sources | array | *undefined* | An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the [cross-browser compatibility](https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats). Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference.
|
||||
prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the subject is supposed to take (e.g., which key to press).
|
||||
width | numeric | width of the video file | The width of the video display in pixels.
|
||||
height | numeric | heigh of the video file | The height of the video display in pixels.
|
||||
|
@ -8,7 +8,7 @@ Parameters with a default value of *undefined* must be specified. Other paramete
|
||||
|
||||
Parameter | Type | Default Value | Description
|
||||
----------|------|---------------|------------
|
||||
sources | array | *undefined* | An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the [cross-browser compatibility](https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats). Usually .mp4 is a safe cross-browser option. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference.
|
||||
sources | array | *undefined* | An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the [cross-browser compatibility](https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats). Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference.
|
||||
prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the subject is supposed to take (e.g., which key to press).
|
||||
width | numeric | width of the video file | The width of the video display in pixels.
|
||||
height | numeric | heigh of the video file | The height of the video display in pixels.
|
||||
|
@ -24,8 +24,8 @@
|
||||
//height: 600,
|
||||
autoplay: true,
|
||||
//controls: true,
|
||||
start: 8.75,
|
||||
stop: 9,
|
||||
//start: 8,
|
||||
//stop: 9,
|
||||
rate: 1.5,
|
||||
//trial_duration: 2000,
|
||||
//trial_ends_after_video: true,
|
||||
|
12
jspsych.js
12
jspsych.js
@ -52,7 +52,7 @@ window.jsPsych = (function() {
|
||||
//
|
||||
|
||||
core.init = function(options) {
|
||||
|
||||
function init() {
|
||||
if(typeof options.timeline === 'undefined'){
|
||||
console.error('No timeline declared in jsPsych.init. Cannot start experiment.')
|
||||
}
|
||||
@ -205,6 +205,14 @@ window.jsPsych = (function() {
|
||||
);
|
||||
};
|
||||
|
||||
// execute init() when the document is ready
|
||||
if (document.readyState === "complete") {
|
||||
init();
|
||||
} else {
|
||||
window.addEventListener("load", init);
|
||||
}
|
||||
}
|
||||
|
||||
core.progress = function() {
|
||||
|
||||
var percent_complete = typeof timeline == 'undefined' ? 0 : timeline.percentComplete();
|
||||
@ -2600,7 +2608,7 @@ jsPsych.pluginAPI = (function() {
|
||||
var loaded = 0;
|
||||
|
||||
if(progress_bar){
|
||||
var pb_html = "<div id='jspsych-loading-progress-bar-container' style='height: 10px; width: 300px; background-color: #ddd;'>";
|
||||
var pb_html = "<div id='jspsych-loading-progress-bar-container' style='height: 10px; width: 300px; background-color: #ddd; margin: auto;'>";
|
||||
pb_html += "<div id='jspsych-loading-progress-bar' style='height: 10px; width: 0%; background-color: #777;'></div>";
|
||||
pb_html += "</div>";
|
||||
jsPsych.getDisplayElement().innerHTML = pb_html;
|
||||
|
@ -138,12 +138,19 @@ jsPsych.plugins["video-button-response"] = (function() {
|
||||
if(trial.height) {
|
||||
video_html += ' height="'+trial.height+'"';
|
||||
}
|
||||
if(trial.autoplay){
|
||||
if(trial.autoplay & (trial.start == null)){
|
||||
// if autoplay is true and the start time is specified, then the video will start automatically
|
||||
// via the play() method, rather than the autoplay attribute, to prevent showing the first frame
|
||||
video_html += " autoplay ";
|
||||
}
|
||||
if(trial.controls){
|
||||
video_html +=" controls ";
|
||||
}
|
||||
if (trial.start !== null) {
|
||||
// hide video element when page loads if the start time is specified,
|
||||
// to prevent the video element from showing the first frame
|
||||
video_html += ' style="visibility: hidden;"';
|
||||
}
|
||||
video_html +=">";
|
||||
|
||||
var video_preload_blob = jsPsych.pluginAPI.getVideoBuffer(trial.sources[0]);
|
||||
@ -155,6 +162,9 @@ jsPsych.plugins["video-button-response"] = (function() {
|
||||
}
|
||||
var type = file_name.substr(file_name.lastIndexOf('.') + 1);
|
||||
type = type.toLowerCase();
|
||||
if (type == "mov") {
|
||||
console.warn('Warning: video-button-response plugin does not reliably support .mov files.')
|
||||
}
|
||||
video_html+='<source src="' + file_name + '" type="video/'+type+'">';
|
||||
}
|
||||
}
|
||||
@ -190,11 +200,13 @@ jsPsych.plugins["video-button-response"] = (function() {
|
||||
|
||||
var start_time = performance.now();
|
||||
|
||||
var video_element = display_element.querySelector('#jspsych-video-button-response-stimulus');
|
||||
|
||||
if(video_preload_blob){
|
||||
display_element.querySelector('#jspsych-video-button-response-stimulus').src = video_preload_blob;
|
||||
video_element.src = video_preload_blob;
|
||||
}
|
||||
|
||||
display_element.querySelector('#jspsych-video-button-response-stimulus').onended = function(){
|
||||
video_element.onended = function(){
|
||||
if(trial.trial_ends_after_video){
|
||||
end_trial();
|
||||
} else if (!trial.response_allowed_while_playing) {
|
||||
@ -205,21 +217,30 @@ jsPsych.plugins["video-button-response"] = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
video_element.playbackRate = trial.rate;
|
||||
|
||||
// if video start time is specified, hide the video and set the starting time
|
||||
// before showing and playing, so that the video doesn't automatically show the first frame
|
||||
if(trial.start !== null){
|
||||
display_element.querySelector('#jspsych-video-button-response-stimulus').currentTime = trial.start;
|
||||
video_element.pause();
|
||||
video_element.currentTime = trial.start;
|
||||
video_element.onseeked = function() {
|
||||
video_element.style.visibility = "visible";
|
||||
if (trial.autoplay) {
|
||||
video_element.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(trial.stop !== null){
|
||||
display_element.querySelector('#jspsych-video-button-response-stimulus').addEventListener('timeupdate', function(e){
|
||||
var currenttime = display_element.querySelector('#jspsych-video-button-response-stimulus').currentTime;
|
||||
video_element.addEventListener('timeupdate', function(e){
|
||||
var currenttime = video_element.currentTime;
|
||||
if(currenttime >= trial.stop){
|
||||
display_element.querySelector('#jspsych-video-button-response-stimulus').pause();
|
||||
video_element.pause();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
display_element.querySelector('#jspsych-video-button-response-stimulus').playbackRate = trial.rate;
|
||||
|
||||
// add event listeners to buttons
|
||||
for (var i = 0; i < trial.choices.length; i++) {
|
||||
display_element.querySelector('#jspsych-video-button-response-button-' + i).addEventListener('click', function(e){
|
||||
@ -273,7 +294,7 @@ jsPsych.plugins["video-button-response"] = (function() {
|
||||
|
||||
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||
// which can be used to provide visual feedback that a response was recorded
|
||||
display_element.querySelector('#jspsych-video-button-response-stimulus').className += ' responded';
|
||||
video_element.className += ' responded';
|
||||
|
||||
// disable all the buttons after a response
|
||||
var btns = document.querySelectorAll('.jspsych-video-button-response-button button');
|
||||
|
@ -119,12 +119,19 @@ jsPsych.plugins["video-keyboard-response"] = (function() {
|
||||
if(trial.height) {
|
||||
video_html += ' height="'+trial.height+'"';
|
||||
}
|
||||
if(trial.autoplay){
|
||||
if(trial.autoplay & (trial.start == null)){
|
||||
// if autoplay is true and the start time is specified, then the video will start automatically
|
||||
// via the play() method, rather than the autoplay attribute, to prevent showing the first frame
|
||||
video_html += " autoplay ";
|
||||
}
|
||||
if(trial.controls){
|
||||
video_html +=" controls ";
|
||||
}
|
||||
if (trial.start !== null) {
|
||||
// hide video element when page loads if the start time is specified,
|
||||
// to prevent the video element from showing the first frame
|
||||
video_html += ' style="visibility: hidden;"';
|
||||
}
|
||||
video_html +=">";
|
||||
|
||||
var video_preload_blob = jsPsych.pluginAPI.getVideoBuffer(trial.sources[0]);
|
||||
@ -136,6 +143,9 @@ jsPsych.plugins["video-keyboard-response"] = (function() {
|
||||
}
|
||||
var type = file_name.substr(file_name.lastIndexOf('.') + 1);
|
||||
type = type.toLowerCase();
|
||||
if (type == "mov") {
|
||||
console.warn('Warning: video-keyboard-response plugin does not reliably support .mov files.')
|
||||
}
|
||||
video_html+='<source src="' + file_name + '" type="video/'+type+'">';
|
||||
}
|
||||
}
|
||||
@ -149,11 +159,13 @@ jsPsych.plugins["video-keyboard-response"] = (function() {
|
||||
|
||||
display_element.innerHTML = video_html;
|
||||
|
||||
var video_element = display_element.querySelector('#jspsych-video-keyboard-response-stimulus');
|
||||
|
||||
if(video_preload_blob){
|
||||
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').src = video_preload_blob;
|
||||
video_element.src = video_preload_blob;
|
||||
}
|
||||
|
||||
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').onended = function(){
|
||||
video_element.onended = function(){
|
||||
if(trial.trial_ends_after_video){
|
||||
end_trial();
|
||||
}
|
||||
@ -169,21 +181,30 @@ jsPsych.plugins["video-keyboard-response"] = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
video_element.playbackRate = trial.rate;
|
||||
|
||||
// if video start time is specified, hide the video and set the starting time
|
||||
// before showing and playing, so that the video doesn't automatically show the first frame
|
||||
if(trial.start !== null){
|
||||
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').currentTime = trial.start;
|
||||
video_element.pause();
|
||||
video_element.currentTime = trial.start;
|
||||
video_element.onseeked = function() {
|
||||
video_element.style.visibility = "visible";
|
||||
if (trial.autoplay) {
|
||||
video_element.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(trial.stop !== null){
|
||||
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').addEventListener('timeupdate', function(e){
|
||||
var currenttime = display_element.querySelector('#jspsych-video-keyboard-response-stimulus').currentTime;
|
||||
video_element.addEventListener('timeupdate', function(e){
|
||||
var currenttime = video_element.currentTime;
|
||||
if(currenttime >= trial.stop){
|
||||
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').pause();
|
||||
video_element.pause();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').playbackRate = trial.rate;
|
||||
|
||||
// store response
|
||||
var response = {
|
||||
rt: null,
|
||||
|
@ -161,12 +161,19 @@ jsPsych.plugins["video-slider-response"] = (function() {
|
||||
if(trial.height) {
|
||||
video_html += ' height="'+trial.height+'"';
|
||||
}
|
||||
if(trial.autoplay){
|
||||
if(trial.autoplay & (trial.start == null)){
|
||||
// if autoplay is true and the start time is specified, then the video will start automatically
|
||||
// via the play() method, rather than the autoplay attribute, to prevent showing the first frame
|
||||
video_html += " autoplay ";
|
||||
}
|
||||
if(trial.controls){
|
||||
video_html +=" controls ";
|
||||
}
|
||||
if (trial.start !== null) {
|
||||
// hide video element when page loads if the start time is specified,
|
||||
// to prevent the video element from showing the first frame
|
||||
video_html += ' style="visibility: hidden;"';
|
||||
}
|
||||
video_html +=">";
|
||||
|
||||
var video_preload_blob = jsPsych.pluginAPI.getVideoBuffer(trial.sources[0]);
|
||||
@ -178,6 +185,9 @@ jsPsych.plugins["video-slider-response"] = (function() {
|
||||
}
|
||||
var type = file_name.substr(file_name.lastIndexOf('.') + 1);
|
||||
type = type.toLowerCase();
|
||||
if (type == "mov") {
|
||||
console.warn('Warning: video-slider-response plugin does not reliably support .mov files.')
|
||||
}
|
||||
video_html+='<source src="' + file_name + '" type="video/'+type+'">';
|
||||
}
|
||||
}
|
||||
@ -234,8 +244,19 @@ jsPsych.plugins["video-slider-response"] = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
video_element.playbackRate = trial.rate;
|
||||
|
||||
// if video start time is specified, hide the video and set the starting time
|
||||
// before showing and playing, so that the video doesn't automatically show the first frame
|
||||
if(trial.start !== null){
|
||||
video_element.pause();
|
||||
video_element.currentTime = trial.start;
|
||||
video_element.onseeked = function() {
|
||||
video_element.style.visibility = "visible";
|
||||
if (trial.autoplay) {
|
||||
video_element.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(trial.stop !== null){
|
||||
@ -247,8 +268,6 @@ jsPsych.plugins["video-slider-response"] = (function() {
|
||||
})
|
||||
}
|
||||
|
||||
video_element.playbackRate = trial.rate;
|
||||
|
||||
if(trial.require_movement){
|
||||
display_element.querySelector('#jspsych-video-slider-response-response').addEventListener('click', function(){
|
||||
display_element.querySelector('#jspsych-video-slider-response-next').disabled = false;
|
||||
|
48
tests/jsPsych/init.test.js
Normal file
48
tests/jsPsych/init.test.js
Normal file
@ -0,0 +1,48 @@
|
||||
require("../../jspsych");
|
||||
require("../../plugins/jspsych-html-keyboard-response");
|
||||
|
||||
describe("jsPsych init", () => {
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = "";
|
||||
});
|
||||
|
||||
function setReadyState(targetState) {
|
||||
jest
|
||||
.spyOn(document, "readyState", "get")
|
||||
.mockImplementation(() => targetState);
|
||||
}
|
||||
|
||||
function getBodyHTML() {
|
||||
return document.body.innerHTML;
|
||||
}
|
||||
|
||||
function init() {
|
||||
jsPsych.init({
|
||||
timeline: [
|
||||
{
|
||||
type: "html-keyboard-response",
|
||||
stimulus: "foo",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
it("should delay execution until the document is ready", () => {
|
||||
expect(getBodyHTML()).toBe("");
|
||||
|
||||
setReadyState("loading");
|
||||
init();
|
||||
expect(getBodyHTML()).toBe("");
|
||||
|
||||
// Simulate the document getting ready
|
||||
setReadyState("complete");
|
||||
window.dispatchEvent(new Event("load"));
|
||||
expect(getBodyHTML()).not.toBe("");
|
||||
});
|
||||
|
||||
it("should execute immediately when the document is ready", () => {
|
||||
// The document is ready by default in jsdom
|
||||
init();
|
||||
expect(getBodyHTML()).not.toBe("");
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user