PuppetMaster Guide - Writing JavaScript Actions
Please note that there will be changes and additions to the JavaScript interface as PuppetMaster is developed.
This is a guide for writing JavaScript actions with PuppetMaster. PuppetMaster is available at http://www.lim.com.au/PuppetMaster
One of the ways of customizing PuppetMaster is using JavaScript.
This is not a tutorial on JavaScript Ð there are plenty of other tutorials on the internet that will teach syntax and features. This is just a guide on how to use JavaScript to provide fine control of PuppetMaster
LetÕs start with an example.
iTunesApp
= new ActiveXObject("iTunes.Application");
iTunesApp.Play();
The script above will cause iTunes to launch and to play.. To use it, go to Preferences -> Menus -> Add Item
Select JavaScript, give it a name, (eg. ÒPlayÓ) and paste the script into it. Click OK.
The action will be added to your Available items. To show it on your phone, drag it across to the left pane. ItÕll appear immediately on your phone if youÕre already connected.
Try it out! Make sure you have iTunes installed. Then click on ÒPlayÓ. You should find that iTunes launches and plays as expected.
This demonstrates how simple non-interactive scripts can be created.
Create a new Java Script action called ÒHello WorldÓ. Paste the following script in
etActivate
= 1;
if(ExecuteData.type
== 1)
{
RemoteController.ShowDialog("Hello
World");
}
When you use this script on your phone, itÕll show ÒHello WorldÓ. Pressing OK or Back buttons will return you to the parent menu.
When PuppetMaster calls the JavaScript, it provides two objects Ð ExecuteData and RemoteController. ExecuteData provides information on why the script is called.
When a script is first selected from a menu, it is sent an etActivate event. If the script does not tell the RemoteController to display anything, then the script is finished with. However, if the script does display something on the RemoteController, then PuppetMaster assigns the script an ÔactiveÕ state and it will be called in the future.
RemoteController provides methods to interact with the device. Here, we are simply displaying the text ÒHello WorldÓ
PuppetMaster will call the script with ExecuteData.Type set to etKeyPress when the user presses a button. Try the following script
etActivate
= 1; etKeyPress = 4;
switch(ExecuteData.Type)
{
case
etActivate:
RemoteController.ShowDialog("Press a
key");
break;
case
etKeyPress:
RemoteController.ShowDialog("You pressed
" + ExecuteData.KeyID);
break;
}
If you look at how this script works, youÕll notice that the actual key pressed is provided by part of ExecuteData
Sometimes youÕd like the script to know Ôwhat happened before.Õ The RemoteController object has a ÒStoreÓ property that you can set to any value (or array of values) that will be preserved across calls. Try the following example
etActivate
= 1; etKeyPress = 4;
switch(ExecuteData.Type)
{
case
etActivate:
RemoteController.ShowDialog("Press a
key");
RemoteController.Store = 0;
break;
case
etKeyPress:
RemoteController.Store =
RemoteController.Store + 1;
RemoteController.ShowDialog(RemoteController.Store
+ ": You pressed " + ExecuteData.KeyID);
break;
}
The Store is initialised to zero in the etActivate section, and is incremented every time a key is pressed. You should see this in the text output on your phone.
Before continuing with example scripts, itÕs worth knowing about the different execute typesÉ
The actual numeric values for the execute types can be found in the Object Reference
etActivate is sent when the script is first clicked on in a menu. If the script does NOT use one of the RemoteController.Show* methods, then no further messages will be sent to the script, and the menu remains active. To be interactive, the script must handle the etActivate message.
etBegin is sent when the script first becomes active. etEnd is sent when the script becomes inactive. To make the script become active, it must use a RemoteController.Show* method in response to an etActivate
etKeyPress and etKeyRelease are messages sent to the script when keys are pressed and released. The ExecuteData.KeyID property can be used to determine which key was pressed/released.
etIntegerInput and etTextInput are messages sent when a value has been entered by the user. Menus send 0-based integer values representing which index was selected.
etNext and etBack are special cases of user input since they are often dealt with in a very different way on the phones. They generally correspond to ÒOKÓ and ÒBackÓ keys. etNext and etBack require that you call a RemoteController.Show* if you wish your script to remain active. Not handling etNext/etBack will cause PuppetMaster to display the parent menu.
The etTimer message is sent periodically to your script to allow updating of the phone based on time. Timers are set using RemoteController.StartTimer(Milliseconds) and stopped using RemoteController.StopTimer()
To get PuppetMaster to call your script periodically, you need to use the RemoteController.StartTimer method. You will also need to tell it to stop triggering periodic events when you exit. The following example uses JavaScriptÕs inbuilt Date function.
etActivate
= 1, etBegin = 2, etEnd = 3, etTimer = 8;
switch(ExecuteData.Type)
{
case
etActivate:
case
etTimer:
RemoteController.ShowDialog(new Date());
break;
case
etBegin:
RemoteController.StartTimer(1000);
break;
case
etEnd:
RemoteController.StopTimer();
break;
}
RemoteController.StartTimer takes a parameter in milliseconds that represents the time between each etTimer message. Running the above example should cause the system time to be displayed on your mobile phone.
The following example gives an idea of how scripts with multiple states can be created. Understanding how it works is left as an exercise to the reader.
etActivate
= 1; etIntegerInput = 6; etNext = 7; etBack = 9;
stMenu
= 0; stDialog = 1; stPercentInput = 2;
function
ShowMenu()
{
RemoteController.Store[0] = stMenu;
RemoteController.ShowMenu("MultiState Example", new
Array("Show Dialog", "Show Percent Input"));
}
function
HandlePercentInput()
{
switch(ExecuteData.Type)
{
case etBack:
case etNext:
ShowMenu();
break;
case etIntegerInput:
RemoteController.Store[1] =
ExecuteData.Input;
break;
}
}
function
HandleDialog()
{
switch(ExecuteData.Type)
{
case etBack:
case etNext:
ShowMenu();
break;
}
}
function
HandleMenu()
{
if(ExecuteData.Type == etIntegerInput)
{
switch(ExecuteData.Input)
{
case 0:
RemoteController.ShowDialog("Current Percent " +
RemoteController.Store[1]);
RemoteController.Store[0] =
stDialog;
break;
case 1:
RemoteController.ShowPercentInput("Enter Percent",
RemoteController.Store[1]);
RemoteController.Store[0] =
stPercentInput;
break;
}
}
}
if(ExecuteData.Type
== etActivate)
{
RemoteController.Store = new Array(2);
RemoteController.Store[0] = stMenu;
RemoteController.Store[1] = 50 // Just
give percent some starting value
ShowMenu();
}
switch(RemoteController.Store[0])
{
case
stMenu:
HandleMenu();
break;
case
stDialog:
HandleDialog();
break;
case
stPercentInput:
HandlePercentInput();
break;
}
The ExecuteData object provides information on why the script is being run.
|
Name |
Notes |
|
Type |
This provides the type. The following are currently defined: etActivate = 1 etBegin = 2 etEnd = 3 etKeyPress = 4 etKeyRelease = 5 etIntegerInput = 6 etBack = 7 etTimer = 8 etNext = 9 etTextInput = 10 These are discussed in the Execute Types section |
|
KeyID |
String value that represents the key pressed. Ò<Ó Ð Left Arrow Ò>Ó Ð Right Arrow Ò^Ó Ð Up Arrow ÒvÓ Ð Down Arrow Ò0Ó Ð Ò9Ó, Ò#, Ò*Ó Ð Keypad ÒuÓ, ÒdÓ - + and Ð buttons on Sony Ericsson phones ÒfÓ Ð Menu Button ÒcÓ Ð Clear button (Not available on all phones) |
|
Input |
Integer value for menus, percent input String value for text input |
The RemoteController object provides access to remote control device.
|
Name |
Notes |
|
CanShowImage |
This returns true or false depending on if the device is capable of displaying images. |
|
Store |
This value is used to store data across multiple script executions. See Persistent Data section. |
|
ImageWidth |
This is the image display width of the device |
|
ImageHeight |
This is the image display height of the device |
|
Name |
Notes |
|
ShowDialog(Text); |
Displays Text on the device |
|
ShowImage ImageFileName, ImageFileType, TimeBeforeHighQuality |
ImageFileName must be a full path to a supported image file type. TimeBeforeHighQuality controls active degradation of the image. If another image has been displayed within the last TimeBeforeHighQuality (in milliseconds), then the image will be converted to a lower quality to improve interactivity if required. To always display a high quality image, specify 0. Showing an image that is of different dimensions to ImageWidth and ImageHeight will cause it to be resized to fit before display. Supported file types are currently: BMP, JPG, PCX, TGA |
|
ShowMenu(Title, MenuArray); |
MenuArray is an array of strings. Sends input via etIntegerInput which is zero-based |
|
ShowPercentInput(Title, StartingPercent); |
Shows a percent input on the phone. etIntegerInput messages will be generated for every change in value. |
|
ShowProgress(Text); |
Shows a progress dialog. |
|
ShowSortedMenu(Title, MenuArray); |
Same as ShowMenu, but will sort the names before display. |
|
ShowText(Title, Text); |
Shows Text on the device. If the text is too long to fit in one screen, the user can scroll it using Up/Down arrows |
|
ShowTextInput(Title, InitialText); |
Allows the user to input text. Most phones support T9 input for this. |
|
Store |
This value is used to store data across multiple script executions. See Persistent Data section. |
|
Mode Type |
Events related to the mode |
|
Dialog |
etKeyPress, etKeyRelease |
|
Text |
etKeyPress, etKeyRelease |
|
Percent Input |
etIntegerInput |
|
Progress |
etKeyPress, etKeyRelease |
|
Menu |
etIntegerInput |
|
Text Input |
etTextInput |
|
Image |
etKeyPress, etKeyRelease |
Comments, corrections, questions? Email me: jeff@lim.com.au