Scripting tools are available to users who wish to take Gorilla to the next level and further customise their tasks by creating and adding new components to the Builder UI. Gorilla scripting tools use the TypeScript programming language.
Navigate the menu to the left to learn more about the tools!
Gorilla Tooling operates based on the Object-Component system. The basic idea is that each element on the screen is an object made up of several components, each of which do different things.
The new scripting tools allow users to create their own components which can provide new, unique functionalities in the tasks. The key point is that every new script created in the Script tab becomes a new component that will show up in the list of components and can be added to the task.
For example, if you create a Task Component called ‘MyNewComponent’ and then go to Displays tab > Object > Add component, you will find ‘MyNewComponent’ appearing on the list of components available to be added to an object. You can combine this component with other components, creating unique objects that meet your specific research needs.
Depending on the functionality you're trying to implement, you will either create a component that is used on the Screen tab (to control things like scoring, saving data or branching), or a component that you add to the Objects tab on the screen itself (to control the appearance or behaviour of individual objects).
Scripting tools are accessible from the Scripting tab, located in the Task Builder menu, on the left-hand side:
When you go to the Scripting tab for the first time, the script editor is blank. In order to start scripting, you must first enter the Edit mode by clicking the Edit button in the top right corner of the Task Builder.
When you are in the Edit mode, in the script tab, you will see a +New Script button in the top right corner. Clicking on the button brings up a menu of script templates for the most common use cases. For information on templates, head to the Use Cases section of this guide.
Gorilla Scripting tools allow you to control almost anything you want within your task, but there are some most commonly used cases for creating custom components in Gorilla. These include creating new screen components, setting up custom spreadsheet randomisation etc.
Templates for the most common scripting cases are available in the Template Menu when creating a new script - these will give you a pre-populated script that you can simply edit and fill in. We generally recommend that you use one of these as a starting point and adapt it to add the functionality you want. You can also choose a completely blank slate and then use one of the other templates from the guides below (or, for tech-savvy programmers, implement your own code).
To see the scripting tools in action, let's create a simple 'Hello World' component. It will allow you to add it to an object on your screen, and contain a single configurable field where you can enter some text. When you preview your task, it will display the text you entered in an alert box.
Firstly, make sure you are editing your task (by clicking the Edit button in the top right corner), open the Scripting tab, and click New Script. You should see the New Script menu:
Choose a Blank Slate for now (we'll talk about the templates later), and name your script HelloWorld.
Next, paste the following code into the editor:
In your task, create a new display and screen (consider using the Instructions Screen template so you've got a working screen), and then click Add Object. Search for HelloWorld, and you should see your new component appear in the list:
Select the object, then click on it on the list of Objects. Add some text into the 'My Setting' box (e.g. put the text "Hello World!"):
Finally, let's preview the functionality of your new component. Click the Play button at the top of the screen, and you should see the text you entered appear in an alert box:
Congratulations, you have added a new scripting component to your task! Now, continue to the next section to learn more about the anatomy of a script.
In this section, we go through elements of a script step by step to help you understand how it's built and how to edit it.
All components in Gorilla follow the same basic structure - whatever kind of component you're making, it will always contain the following parts:
Read about each part below:
This section is optional, but we think it's good practice to have a standard comment block at the top of the script that details what the component does.
You can import any of the Gorilla types from
@gorilla/compiled/task-builder.js. This is the compiled bundle that exports all the types and classes that Gorilla uses. Note that the
@gorilla part is a placeholder - this gets expanded to the correct path when your script is compiled.
If you have multiple scripts of your own, you can import between them using simple relative paths. For example, if you have two scripts called
scriptB.js, and you want to use a class or function from
scriptB.js, you can simply do:
When you create a task, each screen is made up of objects, which in turn have one or more components (see our Object-Component System guide for reference). Each of those components has some settings that you can configure, and we call the structure that contains those settings the component's factory. A factory is simply where you define what the settings are that your component exposes, and in your script, you can access those settings via
this.factory. This allows you to build your component's core functionality without worrying about the specific content that it's going to use - you can think in terms of 'some text' or 'an image', and allow the specific text or image to be specified later (or, indeed, to be different on different screens).
This is the code for the actual component itself. There are a few key parts to this:
@component()directive at the top - this is a special piece of code called a decorator that tells the Gorilla system that your component exists.
... extends TaskComponent<HelloWorldFactory>) to the baseclass - this makes sure that when you access your factory using
this.factoryyou see all of your custom fields.
Note that, most of the time, this will all be done for you when you use a script template - you pick the baseclass you want to start from, and all of these settings will already be configured.
The actual body of the component is where you put your own custom code - you can implement the functionality that you need by implementing one or more core functions. In this HelloWorld example, you can see that we use the
screenStart() function to run some logic when the screen starts. There are several other functions which you can override which get called at key points in the task logic. We call these lifecycle functions (as they are called at specific points in the component's lifecycle). You can see a full list of them here:
This section allows you to specify how your component appears in the Gorilla editor. You can configure a label and an icon, and most importantly, the form fields that should appear in the configuration panel. Crucially, these form elements should match the fields in your component's Factory - this is how you (and others) will configure those factory settings when using your component.
There are several different classes you can use for the editor fields (e.g. text, dropdown, toggle etc) - you can see the full listing of them here:
This final section registers your component with the system, and allows you to add a description. This description will appear in the Add Object and Add Component menus, and should be a short, single sentence describing what your component does.
You can use the Binding system in your scripts to give you access to dynamic variables from the spreadsheet, store, manipulations and so on.
When configuring a field in your component's factory that you want to be bindable, the factory part doesn't change:
You just need to use one of the bindable form types when registering your component:
This will tell the Gorilla editor that, as well as allowing the actual text, you're also happy to receive a
binding string instead. This is a special string that contains information about where to look for a particular value, rather than containing the value itself.
Binding strings have the following format:
So, for example, when bound to a spreadsheet column called
instruction, it would look like this:
If bound to a manipulation called 'prompt', it would look like this:
The simplest way to use a bound field is to simply call
this.injectBindings(). This will invoke the binding system and return the final, resolved value. This is most useful when using a bound value once (e.g. when configuring some text at the start of the screen):
myBindableSetting is bound to (or even if it's not bound at all), the call to
injectBindings will resolve the binding chain and return a value that you can use.
This is fine for many use-cases, but has some drawbacks:
myBindableFieldis bound to changes during the screen, our text will not update, because we only set it once at the start of the screen.
To mitigate the two issues above, you can use a 'live' binding. This takes a little more setup:
To use a live binding, we first need to declare a member variable to hold our Binding object, and create it in our
This creates our binding object, and also allows us to pass in a callback to call whenever the value of the binding changes. In this callback,
value will be the new value of the binding, so we can pass this directly to our
setText() function without needing to call
this.injectBindings() (as this step has already happened).
We also need to pass our factory setting through to our binding in the
Note the call to
super.apply(f) - we need to make sure we still call into our baseclass.
Now that we have an actual binding object, there are some extra things we can do:
Access the resolved value at any time
We can use
this.myBinding.value to access a resolved value for our binding at any time. If there are other lifecycle functions where you want to access the bound value, you can always do so here.
React whenever the bound value changes
We can use the callback we specified in
this.createBinding() to run some logic whenever the bound value changes.
If you are a pro programmer who feels comfortable in scripting environment, you can skip this part. But if you are fairly new to programming, find it challenging or just want to hear some tips that we find helpful, see our top tips below.
This one might seem obvious but do write down your end goal. Make sure it’s specific as this will make writing the script easier.
If you are using scripting tools you probably want to introduce something innovative into your Gorilla task and, like with every big idea, this might initially seem daunting. A helpful strategy is to think of what actions need to happen in your code to achieve your goal and then to break these actions into small steps. Write those steps down - this is a helpful practice to make sure you understand the code and can work through it step by step, in manageable chunks, rather than struggle with a big complicated picture.
Use comments within the script to document every step involved in your code, describe the variables you are using and the purpose and outcome of different functions in your code. This will really help you staying on top of the script, making sure you understand what each part is responsible for. If you have a lot of projects happening simultaneously, or go for a long holiday, these notes will help you stay on track with your work - you will thank yourself later! This practice is also excellent for collaborations and sharing your work with others in the spirit of Open Science 🙂
Once you have your steps written down and therefore are clear on what you need to do in order to write your component, start filling in the steps with code. Gorilla tools uses TypeScript as a programming language.
Before previewing your newly scripted component, fix any errors that might be showing in the error console in your Scripting tab. The error messages displaying in this panel will show errors from all the scripts you have created for this task. It is important that all the errors are corrected because the errors in one script can impact the functionality of another script and therefore your components might not work as intended.
At Gorilla, we are dedicated to providing powerful tools that allow researchers to collaborate and share their work within their team, as well as with broader science community. You can share your work with others on Gorilla Open Materials page. There, you can also see other’s work and use it for your studies - it’s a win-win!
Gorilla Scripting Use Cases
Browse the full list of use-cases
Gorilla Scripting Examples
Library of tasks with example scripting functionality
Form Fields Reference Guide
List of form fields you can use to connect your components to the Gorilla editor UI
Component Lifecycle Methods
Listing of all lifecycle methods you can use in your components
Listing of all types and interfaces used in the Gorilla system