Client

Client

Client is the central connection point for a wrapper to communicate to a PhET-iO simulation. It implements the API to interoperate with the simulation. Client's API with the simulation supports sending messages across the frame, wiring up listeners, sending commands, and receiving events from the simulation.

On a basic level, a PhET-iO Wrapper is just an instance of Client.js talking to the sim. The simplest API is provided via Client.prototype.launchSim. Options to that method provide a reasonably powerful way to customize the sim. See that method's doc as a starting point to understand how a phet-io wrapper talks to the sim.

The wrapper lifecycle as provided by Client is as follows:

  1. Client creation: instantiating and passing an iframe to that Client instance.
  2. Before the sim starts: listeners are added to Client for the following desired callback events.
    • PhET-iO initialized: when the iframe has loaded the simulation, but the sim hasn't launched yet. During this time the wrapper can communicate with the PhET-iO engine before instances are created and the sim begins emitting events. (see Client.prototype.addPhetioInitializedListener)
    • Simulation Initialized: A callback for when the simulation has loaded fully, all static instances have been created, and the sim is ready for interoperation. (see Client.prototype.addSimInitializedListener)
  3. From here Client can be used to send invocation commands to the running simulation, see Client.invoke.

In general, the use of Client involves adding listeners for the above callbacks and then setting the iframe's src attribute to launch the wrapper. Client.launchSim bundles all of those operations into a single function.

This PhET-iO Client communicates to one and only one iframe. There is no support for having two Clients connect to the same sim iframe. This file is available in the main PhET-iO js library import. See the wrapper index for more information.

Constructor

new Client(frame)

Parameters:
Name Type Description
frame HTMLIFrameElement an HTML element that will house the PhET-iO simulation.

Members

(constant) CAMEL_CASE_SIMULATION_NAME :string

the name of the simulation in lowercase camelCasing
Type:
  • string

(constant) PHET_IO_LIB_ABSOLUTE_PATH :string

This is the path where the lib file has been deployed. This path uses the "MAJOR.MINOR" version, excluding the maintenance number, to get automatic bugfixes.
Type:
  • string

(constant) SIMULATION_DISPLAY_NAME :string

the name of the simulation as a title string, e.g. "Simulation Name"
Type:
  • string

(constant) SIMULATION_NAME :string

the hyphenated name of the simulation, e.g. "simulation-name"
Type:
  • string

(constant) SIMULATION_VERSION :string

the full version of the simulation, in the form of "MAJOR.MINOR.MAINTENANCE"
Type:
  • string

(constant) VERSION :string

The version of Client.js
Type:
  • string

(constant) VERSION_MAJOR_MINOR :string

The Simulation version in MAJOR.MINOR form (ignoring maintenance version).
Type:
  • string

Methods

(async, static) createFromStandardWrapper(simFrame, standardPhetioWrapperHTML, launchSimOptions)

Initializes a new Client instance by launching a sim that loads the given Standard PhET-iO Wrapper data.
Parameters:
Name Type Description
simFrame HTMLIFrameElement
standardPhetioWrapperHTML string
launchSimOptions LaunchSimOptions see launchSim

(async, static) getAPIFile(simVersion, optionsopt) → {Promise.<Object>}

Load the phet-io API file and deliver it in the callback. See the PhET-iO API JSON in the wrapper index for more information.
Parameters:
Name Type Attributes Default Description
simVersion string
options Object <optional>
null
Returns:
Type
Promise.<Object>

(static) getBasePhetioTypeName(phetioTypeName) → {string}

Return the "base" name of the phetioType. This strips off the parametric pieces of the string.
Example
phetio.Client.getBasePhetioTypeName( 'PropertyIO.<BooleanIO>' )
-> "PropertyIO"
Parameters:
Name Type Description
phetioTypeName string
Returns:
Type
string

(static) getPhetioOverridesFile(callback, optionsopt)

Load the phet-io overrides file and deliver it in the callback. See the PhET-iO API JSON in the wrapper index for more information.
Parameters:
Name Type Attributes Description
callback function
options Object <optional>

(static) getSimURL(debug) → {string}

Method that gets the URL for launching the PhET-iO simulation HTML. Set the `src` of the iframe with this function's return value. Note that when using Client.launchSim(), that function calls this and sets the source as part of that method.
Example
const productionClientURL = phetio.Client.getSimURL( false );
const developmentClientURL = phetio.Client.getSimURL( true );
Parameters:
Name Type Description
debug boolean whether to load the debug version of the sim, for development purposes. When true, this loads the version of the simulation with more verbose error handling.
Returns:
Type
string

addErrorListener(listener) → {function}

Adds a listener that is called when the sim errors, or if an invocation command from the wrapper causes an error.
Example
// Throw any errors that are returned by the sim, for debugging.
phetioClient.addErrorListener( error => throw error );
Parameters:
Name Type Description
listener function with a single {Error} argument.
Returns:
wrapped function that can be removed with Client.removeMessageListener()
Type
function

addPhetioInitializedListener(listener) → {function}

Adds a listener that is called when the sim frame is ready for intercommunication. This happens even before the sim is ready to launch. When this listener is called, commands can be sent to the PhetioEngineIO element in the sim to configure the sim and wire up listeners to the simulation before other phet-io elements are created and events are emitted. See the sim's PhetioEngineIO element for more information about what can be done with this listener. In this phase, only the `phetioEngine` element is interoperable. This listener will be removed once called, since "PhET-iO initialization" only happens once in the sim lifecycle.
Example
phetioClient.addPhetioInitializedListener( async () => {
 await phetioClient.invokeAsync( 'phetioEngine', 'setRandomSeed', [ randomSeed ] );
 await phetioClient.invokeAsync( 'phetioEngine', 'launchSimulation' );
} );
Parameters:
Name Type Description
listener function called when PhET-iO is initialized in the sim frame
Returns:
wrapped function that can be removed with Client.removeMessageListener()
Type
function

addSimInitializedListener(listener) → {function}

Adds a listener which is called when the sim has been initialized. This is when all screens have been constructed and the sim is ready to be displayed. Listeners added with this function will be able to call into the simulation and customize any phet-io elements that have been created during the startup sequence. Use this function to handle any manipulation of sim elements that is desired before the sim is displays and becomes interactive. This listener will be removed once called, since "sim initialization" only happens once in the sim lifecycle.
Example
simIFrameClient.addSimInitializedListener( function() {
 simIFrameClient.invokeSequence( [ {
   phetioID: 'concentration.concentrationScreen.view.soluteControls',
   method: 'setVisible',
   args: [ false ]
 }, {
   phetioID: 'concentration.concentrationScreen.model.soluteProperty',
   method: 'setValue',
   args: [ 'concentration.solutes.copperSulfate' ]
 } ] );
} )
Parameters:
Name Type Description
listener function called when the sim is initialized
Returns:
wrapped function that can be removed with Client.removeMessageListener()
Type
function

(async) createMigrationEngine() → {Promise.<(MigrationEngine|null)>}

Returns:
- the migration engine set, or none if none was set.
Type
Promise.<(MigrationEngine|null)>

dispose()

Release resources when the Client instance will no longer be used.
Example
// No longer using the phetioClient, so it can be disposed.
phetioClient.dispose();

getConfigFromStandardPhetioWrapper(standardPhetioWrapperHTML)

Decodes the state from a phetioConfig object.
Parameters:
Name Type Description
standardPhetioWrapperHTML string the configuration data generated by Client

getDebugModeEnabled() → {boolean}

Get if debug mode is enabled. This is the same value as using the "?phetioDebug=true" query parameter.
Returns:
Type
boolean

(async) getStandardPhetioWrapper() → {Promise.<string>}

Get the HTML string for the Standard PhET-iO Wrapper based on the current state of the running simulation.
Returns:
Type
Promise.<string>

getStateFromStandardPhetioWrapper(standardPhetioWrapperHTML) → {object}

Given the text from a standardPhetioWrapperHTML, decode and return the simulation state portion within the config.
Parameters:
Name Type Description
standardPhetioWrapperHTML string
Returns:
- the simulation state object
Type
object

invoke(phetioID, method, argsopt, callbackopt)

Primary way to send a command to the simulation frame from the wrapper frame. Given a phet-io element id, method name, and arguments, invoke the method asynchronously and return values and errors (in that order) as parameters in the callback.
Example
// Set the mass of "Planet 1" to be 123.45 (in the units defined by the model)
phetioClient.invoke( 'sim.introScreen.planet1.massProperty', 'setValue', [ 123.45 ] );

// Get the velocity vector for planet1
phetioClient.invoke( 'sim.introScreen.planet1.velocityProperty', 'getValue', [ ],
  function( velocity, error ){ ... }
);
Parameters:
Name Type Attributes Description
phetioID string the id of the phet-io element
method string the name of the phet-io method
args Array.<*> <optional>
dependent on the method to invoke
callback function <optional>
invoked on completion of the invocations. Called with two parameters:
  1. returnValue {*} - value the invoke call returns, undefined if nothing is returned
  2. error {Error|null} - if there was an error during the invoke, that is returned

(async) invokeAsync(phetioID, method, args)

Like invoke, but async and can be run with await. Returns the returnValue, or null if none.
Parameters:
Name Type Description
phetioID string
method string
args Array.<any>

invokeSequence(sequence, callbackopt)

Method to send multiple commands synchronously, useful if the order of messages matters. The callback is called when the entire sequence is complete with return values and errors for all commands.
Example
// Example that sets several values at once, without checking the return values:
phetioClient.invokeSequence( [ {
  phetioID: 'colorVision.singleBulbScreen.model.flashlight.flashlightOnProperty',
  method: 'setValue',
  args: [ true ]
}, {
  phetioID: 'colorVision.singleBulbScreen.model.flashlight.flashlightWavelengthProperty',
  method: 'setValue',
  args: [ 532.5 ] // The middle of the green range
}, {
  phetioID: 'colorVision.singleBulbScreen.model.filter.filterVisibleProperty',
  method: 'setValue',
  args: [ true ]
}] );

// Example that invokes several commands and uses the return values:
phetioClient.invokeSequence( [
  { phetioID: 'sim.introScreen.model.durationProperty', method: 'getValue' },
  { phetioID: 'sim.introScreen.model.cart.vProperty', method: 'getValue' },
  { phetioID: 'sim.introScreen.model.leftForceProperty', method: 'getValue' },
  { phetioID: 'sim.introScreen.model.rightForceProperty', method: 'getValue' },
  { phetioID: 'sim.introScreen.model.netForceProperty', method: 'getValue' }
  ], function( duration, velocity, leftForce, rightForce, netForce,
               durationError, velocityError, leftForceError, rightForceError, netForceError ) {
    // ...
  });
Parameters:
Name Type Attributes Description
sequence Array.<Command> Each "Invocation" entry in the array will be run async.
callback function <optional>
The arguments will depend on the return values of the methods invoked. The args will be first all return values followed by all errors. i.e. if there are five invocations in a sequence call, then there will be ten arguments in the callback. Further more if all are successful but the last, which returns an error, then there are still ten args, but (one indexed) args 6-9 will be null or undefined, and the tenth will be an {Error}.

invokeSequenceAsync() → {Promise.<Array.<any>>}

Like invokeSequence, but async and can be run with await.
Returns:
Type
Promise.<Array.<any>>

(async) launchSim(providedOptionsopt) → {Promise.<Client>}

This function is the main launch point for launching a PhET-iO simulation. At its core, it sends a message into the simulation to begin. Some options can be very helpful in customizing the simulation run before the launch command has been sent to the sim, see LaunchSimOptions object for more.
Example
// Start the simulation with specific customizations, specified below.
// Example from a wrapper using Hooke's Law
phetioClient.launchSim( {
  queryString: 'screens=3&phetioEmitStates=false',

  // Callback for messages (events) from the sim's data stream
  onEvent: function( event ) {
    // ...
  },

  // Callback when PhET-iO is ready, before the simulation has started initialization
  onPhetioInitialized: async function() {

    // add a listener called whenever a phet-io element is created in the simulation, print out that created phetioID
    await phetioClient.invokeAsync( 'phetioEngine.phetioElementAddedEmitter', 'addListener', [
      function( phetioID ) {
        console.log( phetioID + ' has been created' );
      } ] );
  },

  // Callback when the sim is initialized
  onSimInitialized: async function() {
    console.log( 'sim initialized' );

    // Invoke a method on a variable in the simulation. Open the "Studio" wrapper to see all of the variables
    // and methods available in {{SIMULATION_NAME}} {{SIMULATION_VERSION}}
    await phetioClient.invokeAsync( 'phetioEngine', 'getState', [], function( state ) {
      console.log( 'got the simulation state: ' + JSON.stringify( state, null, 2 ) );
    } );
  }
} )
Parameters:
Name Type Attributes Description
providedOptions LaunchSimOptions <optional>
optional parameters to pass to the launch sequence
Returns:
Type
Promise.<Client>

(async) loadStandardPhetioWrapperFromHTML() → {Promise.<string>}

Returns:
Type
Promise.<string>

removeMessageListener(messageListener)

Removes a listener that receives a callback when a message is received from the simulation frame.
Parameters:
Name Type Description
messageListener function wrapped listener returned from the function adding the listener

setDebugModeEnabled(debugModeEnabled)

Set if debug mode is enabled. This is the same value as using the "?phetioDebug=true" query parameter. In general it is preferable to use the query parameter instead of this method, since hard coding debug mode can be dangerous.
Parameters:
Name Type Description
debugModeEnabled boolean if debug-mode is enabled

(async) setStateFromConfig(config) → {Promise.<void>}

Set the state to the simulation given a configuration data.
Parameters:
Name Type Description
config object the configuration data generated by Client
Returns:
Type
Promise.<void>

(async) setTargetAPIVersion(targetAPIVersion) → {Promise.<void>}

Set the sim version associated with the version of the sim the wrapper was created to work with. This is used to support API migrations with newer versions of the Sim and the PhET-iO API.
Parameters:
Name Type Description
targetAPIVersion string the sim version
Returns:
Type
Promise.<void>

setValues(map, callbackopt)

Convenience function for setting several PropertyIO values. Note the order of application is not guaranteed.
Example
phetioClient.setValues( {

 // Properties
 'hookesLaw.energyScreen.view.viewProperties.appliedForceVectorVisibleProperty': true,
 'hookesLaw.energyScreen.view.viewProperties.displacementVectorVisibleProperty': true,

 // Visibility control panel (top right)
 'hookesLaw.energyScreen.view.visibilityControls.separator.visibleProperty': false,

 // Radio buttons
 'hookesLaw.energyScreen.view.visibilityControls.barGraphRadioButton.visibleProperty': false,
 'hookesLaw.energyScreen.view.visibilityControls.energyPlotRadioButton.visibleProperty': false,
 'hookesLaw.energyScreen.view.visibilityControls.forcePlotRadioButton.visibleProperty': false,
} );
Parameters:
Name Type Attributes Description
map Object.<string, *> the key is the phetioID, and the value is the value given to the "setValue" method
callback function <optional>
callback passed to `invokeSequence`. See that method for details