跳转至

开发扩展

扩展的要求

在7.0版本中,扩展通过JavaScript类实现。扩展中需要实现:

模板

可以使用JavaScript或TypeScript编写扩展。JavaScriptTypeScript的模板文件可以在jspsych-contrib仓库中找到。

扩展的构成

constructor()

扩展的constructor()会接收一个JsPsych的实例,constructor函数需要将其保存下来用于访问。

class MyAwesomeExtension {
  constructor(jsPsych){
    this.jsPsych = jsPsych;
  }
}

initialize()

initialize()函数在初始化jsPsych实例的时候调用 (通过initJsPsych()new JsPsych())。初始化扩展的代码应该下载这个函数里。不同于其他事件每个试次都会触发,每个实验只会初始化一次。params对象中包含了配置扩展所需要的参数,它会在调用传递给initialize()方法,此时initialize()需要返回一个Promise对象,在扩展完成初始化后执行。

//... experiment code ...//
let jsPsych = initJsPsych({
  extensions: [
    {type: myAwesomeExtension, params: {demo: 'value'}}
  ]
});

//... extension code ...//
class MyAwesomeExtension {

  initialize(params){
    return new Promise((resolve, reject)=>{
      console.log(params.demo); // will output 'value'

      resolve(); // finish initialzing
    })
  }
}

on_start()

on_start()在插件开始执行时先于plugin.trial调用。和试次相关的初始化代码应该写在这里,例如创建用于存储数据的对象、重置内部状态等。params对象通过扩展的声明传入试次对象,我们可以使用该对象自定义扩展在各个试次中的行为。

//... experiment code ...//
let trial = {
  type: htmlKeyboardResponse,
  stimulus: "You're awesome!",
  extensions: [
    {type: myAwesomeExtension, params: {demo: 'value'}}
  ]
});

//... extension code ...//
class MyAwesomeExtension {

  initialize(params){ ... }

  on_start(params){
    console.log(params.demo); // outputs 'value' before the trial begins.
  }
}

on_load()

on_load()在插件的on_load()完成后调用,通常是在插件完成对DOM元素的修改以及创建事件的监听器之后。和DOM交互、存储数据的代码应该写在这里。params对象通过扩展的声明传入试次对象,我们可以使用该对象自定义扩展在各个试次中的行为。

//... experiment code ...//
let trial = {
  type: htmlKeyboardResponse,
  stimulus: "You're awesome!",
  extensions: [
    {type: myAwesomeExtension, params: {demo: 'value'}}
  ]
});

//... extension code ...//
class MyAwesomeExtension {

  initialize(params){ ... }

  on_start(params){ ... }

  on_load(params){
    // replaces the contents of the display with 'value';
    this.jsPsych.getDisplayElement().innerHTML = params.demo;
  }
}

on_finish()

on_finish()在插件调用jsPsych.finishTrial()后调用。该方法应该返回一个数据对象,用于添加到插件的数据对象。请注意,这个事件在插件的on_finish 之前 触发,所以其数据可以在试次的on_finish中使用。params对象通过扩展的声明传入试次对象,我们可以使用该对象自定义扩展在各个试次中的行为。

//... experiment code ...//
let trial = {
  type: htmlKeyboardResponse,
  stimulus: "You're awesome!",
  extensions: [
    {type: myAwesomeExtension, params: {demo: 'value'}}
  ],
  on_finish: (data) => {
    console.log(data.awesome); // will output 'value'.
  }
});

//... extension code ...//
class MyAwesomeExtension {

  initialize(params){ ... }

  on_start(params){ ... }

  on_load(params){ ... }

  on_finish(params){
    return {
      awesome: params.value
    }
  }
}

静态的 .info

info属性是一个对象,必须有name属性,作为扩展的唯一名称。

class MyAwesomeExtension {

}

MyAwesomeExtension.info = {
  name: 'awesome'
}

可选方法

扩展还可以额外加入一些方法。参见webgazer扩展

关于编写扩展的建议

如果你希望将开发的扩展加入到jsPsych的主仓库中,请参照贡献代码指南

总的来说,扩展应该适配所有插件,对于DOM中除了实验元素之外还包括了什么不应该有太多限制。如果你开发的扩展只针对少数几个插件,可以考虑修改插件代码。