Invoking a JavaScript Function From Within the Simulation

From SIMboxWiki
Jump to navigation Jump to search

Overview

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.
    Java-html1.png
  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
    Java-html2.png
  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”).
    Java-html3.png
  4. After adding both of the events this should be the state of the agent.
    Java-html4.png

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="http://www.w3.org/1999/xhtml">
<head>
	<title>Untitled Page</title>
</head>
<body>
test page
<script type="text/javascript">
function TestScript(message)
{
	alert(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;
      paramArray.Add(L"Test");

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

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

      // 3. Get the document handle of the HTML page
      int attSceneHtmlDocumentHandle = 0;
      GET_OTHER_ENTITY_ATT_BY_UNIT(entityId, _T("ATT_SCENE_HTML_DOCUMENT_HANDLE"), attSceneHtmlDocumentHandle, UNIT_TYPE_DEFAULT);
      if (attSceneHtmlDocumentHandle == NULL)
      {
            AfxMessageBox(_T("No document handle found"));
            return;
      }

      // 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);
      if(FAILED(hr))
      {
            AfxMessageBox(_T("failed get_Script"));
            return;
      }
      // 6. Get the function 'pointer'
      CComBSTR bstrMember(sScriptName.c_str());
      DISPID dispid = NULL;
      hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,
                                          LOCALE_SYSTEM_DEFAULT,&dispid);
      if(FAILED(hr))
      {
            AfxMessageBox(_T("failed GetIDsOfNames"));
            return;
      }

      // 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
            bstr.CopyTo(&dispparams.rgvarg[i].bstrVal);
            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,
                                          DISPATCH_METHOD,&dispparams,
                                          &vaResult,&excepInfo,&nArgErr);
      // 10. Free resources
      delete [] dispparams.rgvarg;

      if(FAILED(hr))
      {
            AfxMessageBox(_T("failed Invoke"));
            return;
      }

}