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

(static, constant) CAMEL_CASE_SIMULATION_NAME :string

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

(static, 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

(static, constant) SIMULATION_DISPLAY_NAME :string

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

(static, constant) SIMULATION_NAME :string

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

(static, constant) SIMULATION_VERSION :string

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

(static, constant) VERSION :string

The version of Client.js
Type:
  • string

Methods

(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 or not 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
destinationClient.addPhetioInitializedListener( function() {
 destinationClient.invoke( 'phetioEngine', 'setRandomSeed', [ randomSeed ], function() {
   destinationClient.invoke( '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

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();

invoke(phetioID, method, argsopt, callbackopt)

Primary way to send a command to the simulation frame from the wrapper frame. Given an 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

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}.

launchSim(optionsopt)

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',

  // Data stream customizations
  // Choose whether the sim should emit json states and/or input events in addition to the instance-based messages.
  // This can be overridden by query parameters in the wrapper.
  emitStates: 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: function() {

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

  // Callback when the sim is initialized
  onSimInitialized: 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}}
    phetioClient.invoke( 'phetioEngine', 'getState', [], function( state ) {
      console.log( 'got the simulation state: ' + JSON.stringify( state, null, 2 ) );
    } );

    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
options LaunchSimOptions <optional>
optional parameters to pass to the launch sequence

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

setTargetAPIVersion(targetAPIVersion)

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

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