Invoking a JavaScript Function From Within the Simulation

From SIMboxWiki
Jump to navigation Jump to search


Using the simulation you can invoke a Javascript function from an HTML page in order to perform various actions (for example, creating “focal points” in the HTML).
This tutorial will cover the following parts:

  1. Open an HTML page from the Agent Editor.
  2. Create and use a new event to execute the script.
  3. Edit the HTML page to hold your code.
  4. Write a simulation extension that will invoke Javascript functions from the HTML page.

Open an HTML page from the agent editor

  1. Create/Open agent using agent editor.
  2. In the Agent Editor, right-click on Instructions -> Instructional Aids -> Windows Management to open the “Windows Management”.
  3. On the “Window Management” page: 
    a. Action -> New Window.
    b. Window Name -> Enter a unique name, this will be the name of the new HTML window (in this example we will use “HTML View”).
    c. Window Type -> HTML View.
    d. Param1 -> Enter the full file path of the HTML you want to open (in this example we will use “C:\Program Files (x86)\SimiGon\Sitec\Resource\HTML\Test.html”).
    e. Press the “OK” button to save the changes.
  4. Save the agent.

Create and use a new event to execute a script

  1. Create a new event that will execute the script (in this example let call it “ExecuteScript”).
    a. Open the SIMbox Toolkit.
    b. Components -> Events -> Add New
  2. Add two parameters to the new event.
    a. Name: ScriptName, Description: Script function name, Parameter Type: String
    b. Name: WindowName, Description: HTML window name, Parameter Type: String
  3. Add to the agent from the previous section a call to the new event.
    Right-click on Instructions -> Advanced -> Publish Event -> Execute Script.
    i. ScriptName – Enter the name of the script (in this example let call it “TestScript”).
    ii. WindwoName – Enter the name of the window from the “Open Window” Event (in this example it is called “HTML View”).
  4. After adding both of the events this should be the state of the agent.

Edit the HTML page to hold your code

Create an HTML page that holds some functions (in this example we will use a simple function that will show the user a message box):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional>
<html xmlns="">
	<title>Untitled Page</title>
test page
<script type="text/javascript">
function TestScript(message)

Write simulation extension that will invoke Javascript functions from the HTML page

  1. Create a new extension (Open Visual Studio -> New -> Project -> SIMBOX Extension Project).
  2. Add an attribute change to the new event we created (right-click on the project -> Wizard -> Event -> Add -> “ExecuteScript”).
  3. Add the header “Mshtml.h” to the code.
  4. Invoke the Javascript function in the callback function using the following code:
void FocalPointHTML::CBFuncGlobalEventExcuteScript( const SimApi::EventParams* i_Param )

	  std::wstring sScriptName;
      i_Param->getParam(_T("ScriptName"))->getValue( sScriptName);
  	  std::wstring sWindowName;
	  i_Param->getParam(_T("WindowName"))->getValue( sWindowName);

	  // 1. Create parameter list using CStringArray
          // This should be promoted to an event parameter if you wish to pass over arguments to the 
          //script function in this sample we are using hard coded single string parameter ("Test")
      CStringArray paramArray;

	  // 2. Find the window entity
      int entityId = SimApi::Entities::getEntityIDByName(sWindowName);

      if (entityId < 0)
            AfxMessageBox(_T("No window found"));

      // 3. Get the document handle of the HTML page
      int attSceneHtmlDocumentHandle = 0;
      if (attSceneHtmlDocumentHandle == NULL)
            AfxMessageBox(_T("No document handle found"));

      // 4. Get the document object
      LPDISPATCH document = (LPDISPATCH)attSceneHtmlDocumentHandle;
      IHTMLDocument * doc = (IHTMLDocument *)document;

      // 5. Get the script object
      LPDISPATCH spScript;
      HRESULT hr = doc->get_Script(&spScript);
            AfxMessageBox(_T("failed get_Script"));
      // 6. Get the function 'pointer'
      CComBSTR bstrMember(sScriptName.c_str());
      DISPID dispid = NULL;
      hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,
            AfxMessageBox(_T("failed GetIDsOfNames"));

      // 7. Create function arguments struct
      DISPPARAMS dispparams;
      const int arraySize = paramArray.GetSize();
      memset(&dispparams, 0, sizeof dispparams);
      dispparams.cArgs      = arraySize;
      dispparams.rgvarg     = new VARIANT[dispparams.cArgs];
      dispparams.cNamedArgs = 0;

      // 8. Putting parameters in the struct
      for( int i = 0; i < arraySize; i++)
            CComBSTR bstr = paramArray.GetAt(arraySize - 1 - i); // back reading
            dispparams.rgvarg[i].vt = VT_BSTR;
      EXCEPINFO excepInfo;
      memset(&excepInfo, 0, sizeof excepInfo);
      CComVariant vaResult;
      UINT nArgErr = (UINT)-1;  // initialize to invalid arg

      // 9. Call JavaScript function         
      hr = spScript->Invoke(dispid,IID_NULL,0,
      // 10. Free resources
      delete [] dispparams.rgvarg;

            AfxMessageBox(_T("failed Invoke"));