PhET-iO Logo

PhET-iO API Documentation

This documentation is supplemental to the "Wrapper Development" explanation and basic wrapper template example located in the wrapper index. There you can find multiple example wrappers, and a step by step guide to create your own PhET-iO wrapper. See the wrapper index as a starting point. From there use these API docs utilize the complete PhET-iO API.

Basic PhET-iO Wrapper Examples

The simplest way to create a wrapper is with Client.launchSim. Please see the Wrapper Index for a more in depth example, and see the LaunchSimOptions API for details about the capabilities of launchSim.


const simFrame = document.getElementById( 'sim' );
const phetioClient = new phetio.Client( simFrame );

phetioClient.launchSim( {
  onSimInitialized: () => {
    console.log( 'sim initialized' );
  }
} );

The launchSim method is meant to be a simplified, one-stop shop for wrapper development, but some wrappers require more control. For example, if there are two sims, and therefore two PhET-iO Clients, and one sim needs to wait for the other to launch before launching itself (see that PhET-iO State example wrapper). Here is an example of starting up a wrapper with a bit more control. This is equivalent to the above example.

const simFrame = document.getElementById( 'sim' );
const phetioClient = new phetio.Client( simFrame )
phetioClient.addSimInitializedListener( () => {
  phetioClient.invoke( 'phetioEngine', 'displaySim' );
} );
phetioClient.addPhetioInitializedListener( () => {
  phetioClient.invoke( 'phetioEngine', 'launchSimulation' )
} );
simFrame.src = phetio.Client.getSimURL( true ); // load the sim in debug mode

See the entire documentation for Client (here in the API docs), and for PhetioEngineIO (in PhET-iO Studio) to gain a complete idea of all that a wrapper can control in a PhET Simulation.

The Standard PhET-iO Wrapper

When customizing the sim within PhET-iO Studio, you can save this into a "Standard PhET-iO Wrapper". This wrapper supports loading the sim into a custom startup state. This wrapper is not only available through PhET-iO Studio, but also can be created directly though Client commands. Also note that the Standard PhET-iO Wrapper supports an easier update migration to newer versions than Custom PhET-iO wrappers.


// on an already launched sim . . .
const myStandardWrapperHTML = await myClient.getStandardPhetioWrapperHTML();

You can create a Client specifically for loading a Standard PhET-iO Wrapper state:

  const myStandardWrapper = await fetch( './myStandardWrapper.html' );
  const htmlText = await myStandardWrapper.text();
  const simFrame = document.getElementById( 'sim' );
  const phetioClient = await phetio.Client.createFromStandardWrapper( simFrame, htmlText );

More complex cases can take control of the launch sequence:

  const myStandardWrapper = await fetch( './myStandardWrapper.html' );
  const htmlText = await myStandardWrapper.text();
  const simFrame = document.getElementById( 'sim' );
  const phetioClient = new phetio.Client( simFrame );
  phetioClient.launchSim( {
    displaySim: false,
    onSimInitialized: async function() {
    
      // Load the Standard Wrapper customizations into the running sim.
      await phetioClient.loadStandardPhetioWrapperFromHTML( htmlText );
      
      // Display the sim after setting these customizations to prevent a startup "flicker".
      await phetioClient.invokeAsync( 'phetioEngine', 'displaySim' );
    }
  } );

Updating to a newer version

PhET-iO releases simulation updates for many reasons, including:

  • Addressing bugs or issues in the simulations
  • Adding new features
  • Improving consistency within a simulation or across many simulations
  • Working around bugs introduced in browser updates

A PhET-iO simulation consists of two distinct layers.

  1. The wrapper communication layer defines a protocol for launching and communicating with the simulation. That documentation is described here in the API docs. Like a conventional software project, changes to this layer will be accompanied by a list of breaking changes to help update your usages. It is a PhET-iO implementation goal to minimize breaking changes in this layer to reduce the development burden on PhET-iO clients.

  2. The simulation layer defines the PhET-iO Elements and the methods that can be called on them, as well as the arguments which may be passed to the method. A PhET-iO simulation may have thousands of PhET-iO Elements, so the process of providing a list of breaking changes and requiring the client to update numerous sites is much more complex. Therefore, we provide additional support at this level to streamline the process in this layer.

Updating the Standard PhET-iO Wrapper via Studio

When a Standard PhET-iO Wrapper is saved from Studio, it can be loaded back into that version of Studio and into Studio of the next minor version of that simulation. (Studio cannot load save files from later versions.) For example, a Standard PhET-iO Wrapper customized from Gravity and Orbits 1.5 can be loaded into Studio of Gravity and Orbits 1.6. When Studio loads a simulation from a prior version, it will show a message indicating which PhET-iO Elements have changed, so those features can be more focused during QA testing. In any case, the upgraded Standard PhET-iO Wrapper should be thoroughly tested before it is used in production.

Updating a Custom PhET-iO Wrapper

When developing a Custom PhET-iO Wrapper, there are two sites that specify the simulation version. First, there is a <script src=...> tag that shows the URL of the PhET-iO lib for the simulation. Second, there is an option in the phetioClient.launchSim() call described like so:

    /**
     * Set the simulation version that this wrapper was developed with. This is used to migrate this wrapper to future
     * versions of PhET-iO.
     */
    targetAPIVersion: '1.5'

Changing the <script src=...> tag while leaving the targetAPIVersion as the prior version enables a compatibility mode where PhET-iO Elements/methods/arguments from the prior version can be automatically migrated to the newer version. When the Custom PhET-iO Wrapper calls phetioClient.invoke or phetioClient.invokeSequence with PhET-iO Element names or method names that no longer exist in the new version, one of two things will happen:

  • The PhET-iO Element name/method name/arguments will be seamlessly upgraded to the new version and a message will be printed to the console about the change. A Custom PhET-iO Wrapper developer can read those messages during development and testing and use them to help identify which parts of their code should be updated.
  • In some cases, where there is no automatic version upgrade, a message will be printed on the console and the wrapper will cease to function. In these cases, the Custom PhET-iO Wrapper developer will need to manually determine the appropriate way to update the wrapper.

After applying changes from those kinds of upgrades, the Custom PhET-iO Wrapper should be thoroughly tested before it is returned to production.

These facilities have been developed in order to allow PhET-iO to evolve while minimizing the amount of burden on PhET-iO Clients. These processes are still subject to adjustment and improvement as we learn more.