Updated Tutorial Available
This tutorial is for the Desktop Designer. To view the updated tutorial for the online project designer, please click here .

Javascript Point

Learn how the javascript point can be used and see it in action with the sample projects.

What is the Javascript point?

The Javascript Point allows you to add Javascript code to your sessions which can be executed when a user clicks a button or when one of the Session Lifecycle callbacks has occurred. With a basic understanding of the Javascript programming language, this point can be used to perform advanced calculations or other pre-processing changes to your session data.

Key Features

  • Add custom javascript code that can be executed while a session is created on the mobile application.
  • Can optionally provide a button which can be used to trigger execution of custom javascript.
  • Provides the ability to perform advanced processing or calculations on session data and save the results to the session.
  • Can be used with a HTML point to display results on screen.
  • Can be used with sub project points to process data for child and/or parent sessions.

On button press

Javascript Tutorials and Examples

Javascript is an easy-to-learn programming language and there is a helpful and active online community that can help you to get started with learning the language or jumping straight in with working samples of code. Here are some links that may help you get started:

Javascript Editors and Tools

In order to write Javascript, we recommend that you write your javascript code using one of the following tools. The basic editors should be enough for simple javascript but if you would like more advanced features then the advanced editors might be more suitable.

Basic Editors:

Advanced Editors:


Configuration and Settings

The javascript point can be configured in the Mobile Data Anywhere Designer to specify the display mode, button title and the javascript code to be executed. Below is an example of the properties window for a Javascript point, opened in the Mobile Data Anywhere Designer.


On button press

Options

The Display Mode for a Javascript Point can be one of two options; No Interface or Just a Button. When No Interface is selected, the javascript point won’t be appear in the session on the mobile application. The javascript will be executed using the session lifecycle and point callbacks. When Just a Button is selected, the javascript point will appear as a button in the session. The button title setting will be used to customise the text that is displayed on this button.

The Javascript Code section is where you can add javascript code. You can import javascript from an existing javascript file using the Import .js file button.


Did You Know?
You can use a third party tool to maintain your javascript code and simply import the file when you are finished making changes. This will give you the advantage of being able to validate your javascript code before uploading the project file.

Javascript Versions and Availability

In order to improve and add new functionality to the Javascript point, certain callbacks, parameters and other features will be introduced in new versions of the javascript implementation. These changes will only be available on devices that have installed a Mobile Data Anywhere app with the required javascript version. The table below shows which app version is required in order to use the features of a particular javascript version.

To determine which version of the app you have installed on a device, please refer to the guide on Installing Updates via The Settings Page .

Javascript Versions

Javascript Version Apple iOS devices Google Android devices
1.2 Mobile Data Anywhere 1.1.44+ Mobile Data Anywhere 1.1.55+
1.1 Mobile Data Anywhere 1.1.41+ Mobile Data Anywhere 1.1.43+
1.0 All prior versions All prior versions

Javascript Changelog

Javascript Version Changes
1.2
  • Added ability to update multiple sessions, including sessions from same and/or other projects. Prior versions only allowed saving data to the opened session.
  • Added ability to show/hide points similar to logic point.
  • Added created, saved dates and integer timestamps to session summaries that are stored in javascript. This can be useful for sorting session summaries.
1.1

Supporting previous javascript versions

If you want to use a feature from a new javascript version but still want to support previous javascript versions then you will need to use javascript version checking. See below for an example or download the Javascript Device Information sample project .

Javascript Version Checking

The example below shows how to check if the device supports javascript 1.1 or greater

Show example
x={
  onSessionStart: function() {
    var changes = {};
    if (typeof javascriptVersion !== "undefined" && javascriptVersion >= 1.1) {
      // Compatible javascriptVersion
      changes["supportedVersion"] = 1;
      printObject(deviceInformation); // Requires javascriptVersion 1.1+
    } else {
      // Legacy javascriptVersion
      changes["supportedVersion"] = 0;
      return changes;
    }

    // Requires javascriptVersion 1.1+
    changes["javascriptVersion"] = javascriptVersion.toString();
    changes["systemPlatform"] = systemPlatform;
    changes["app"] = deviceInformation["app"];
    changes["appName"] = deviceInformation["appName"];
    changes["appVersion"] = deviceInformation["appVersion"];
    changes["appBuild"] = deviceInformation["appBuild"];
    changes["deviceModel"] = deviceInformation["deviceModel"];
    changes["deviceSystem"] = deviceInformation["deviceSystem"];
    changes["deviceVersion"] = deviceInformation["deviceVersion"];
    return changes;
  }
}

Javascript Dialogs

Javascript alert and confirm dialogs can be displayed on a device to provide the user with a simple message or to present a question and wait for a response.

Javascript point alert Javascript point confirm

Compatibility

There are two implementations available for javascript dialogs however the legacy dialogs are no longer supported and can cause issues for Apple devices running iOS 11 or greater. If you wish to use the app on iOS 11+ devices, please ensure the app is updated to the latest version and that the javascript uses the new javascript dialogs.

The new javascript dialogs are only available in recent versions of the Mobile Data Anywhere app. If you are unable to update to the latest version of the app or require a period to transition then you can use javascript compatibility checking to use the legacy dialogs for older version. Please see the Javascript Versions and Availability for more details.

Alert dialog

An alert dialog allows you to display a message to the user with a single 'OK' button that can be pressed to dismiss the message.

Displaying a message using an alert dialog

Description:

The example below shows how an alert dialog can be used to display a message, wait for the user to close the alert and then save changes back to the session. This uses the onButtonPress callback to execute the javascript that displays the dialog and then it uses the onAlertClosed callback to handle the user's response to the alert dialog.

Show example
x={
  onButtonPress: function() {
    var changes = { "alternativeAlertStatus": "Waiting for user to close alert." };
    this.alertDialog('A message displayed using alertDialog()');

    // NOTE: Unlike legacy javascript dialogs, the new dialogs do not pause javascript execution.
    // Any code after calling this.alertDialog will continue to be executed.
    // This example demonstrates how you can save a value to the session while waiting for the
    // user to finish responsding to the dialog.
    return changes;
  },
  onAlertClosed: function() {
    // This will execute after the user has pressed the OK button to dismiss the alert.
    var changes = { "alternativeAlertStatus": "Alert has closed." };
    return changes;
  }
}
Show example using Legacy Alert Dialog

Legacy Javascript Dialogs are not supported on recent Apple iOS versions (iOS 11+). Please use the new Javascript Dialogs if you wish to deploy projects to devices running iOS 11 or greater.

Using Legacy Javascript Alert Dialog:
x={
  onButtonPress: function() {
    var changes = { "standardAlertStatus": "Waiting for user to close alert." };
    alert('A message displayed using legacy alert()');

    // NOTE: This will not execute until the user has dismissed the displayed alert.
    changes["standardAlertStatus"] = "Alert was closed";
    return changes;
  }
}

Passing custom parameters through an alert dialog

The new javascript alert dialog has an optional parameter for you to pass in a dictionary of custom parameters. This can be useful for passing in data which can then be retrieved in the onAlertClosed callback . You can then continue processing the data with the user's response to the alert and then save any changes back to the session. This functionality is only available in the New Javascript Dialogs and is not available in the Legacy Javascript Dialogs.

This example is also available in the Javascript Sample Dialogs project which can be downloaded or imported into your account at the bottom of this page .

Description:

This example shows how custom parameters can be passed into an alert dialog and then retrieved in the onAlertClosed callback . The javascript is triggered when the Selection Point with ID onetwothree changes value, using the onPointValueChanged callback .

This example demonstrates two ways of retrieving the value of the point that changed. The onPointValueChanged callback was updated to provide the pointValue parameter in version 1.1 of the javascript point.

Show example
x={
  onPointValueChanged: function(pointId, pointValue) {
    if(pointId == "onetwothree") {
       var isLegacyVersion = false;
       if(typeof javascriptVersion === "undefined" || javascriptVersion < 1.1) {
          // Legacy support
          // Version 1.1 added the pointValue parameter to the onPointValueChanged callback.
          // If using an older version of the app with an older javascript version, retreive
          // the pointValue the another way.
          isLegacyVersion = true;
          pointValue = this.project.session['onetwothree'];
       }

       if (!pointValue) {
          // If the value is empty, undefined, null, untruthy... don't show an alert.
          return { "alertWithIdentifierStatus": "Deselected.", "alertIdentifier": "" };
       }

       var customParameters = { "myAlertId": pointValue };
       if (isLegacyVersion) {
         return { "alertWithIdentifierStatus":"Update the Mobile Data Anywhere app to use the new javascript alerts."};
       } else {
         this.alertDialog("Alert with ID:" + pointValue, customParameters);
       }

       return;
    }
  },
  onAlertClosed: function(customParameters) {
    var thisAlertId = customParameters["myAlertId"];
    return { "alertWithIdentifierStatus": "The alert with id " + thisAlertId + " has closed.", "alertIdentifier":thisAlertId };
  }
}

Confirm dialog

A confirm dialog can be used to present a question to the user with two responses; OK and Cancel.

Displaying a question using a confirm dialog

Description:

The example below shows how a confirm dialog can be used to display a question, wait for the user to press OK or Cancel and then save changes back to the session. This example uses the onButtonPress callback to execute the javascript that displays the dialog and then it uses the onConfirmClosed callback to handle the user's response to the confirm dialog.

Show example
x={
  onButtonPress: function() {
    var changes = { "alternativeConfirmStatus": "Waiting for user to close confirm dialog." };
    this.confirmDialog('A question displayed using a confirmDialog().Do you want to confirm or cancel?');

    // NOTE: Unlike standard javascript dialogs, the alternative dialogs do not pause javascript execution.
    // Any code after calling this.alertDialog will continue to be executed.
    // This example demonstrates how you can save a value to the session while waiting for the
    // user to finish responsding to the dialog.
    return changes;
  },
  onConfirmClosed: function(response) {
    // This will execute after the user has pressed either confirm/cancel on the confirm dialog.
    if (response) {
      return { "alternativeConfirmStatus": "OK was pressed." };
    } else {
      return { "alternativeConfirmStatus": "Cancel was pressed." };
    }
  }
}
Show example using Legacy Confirm Dialog

Legacy Javascript Dialogs are not supported on recent Apple iOS versions (iOS 11+). Please use the new Javascript Dialogs if you wish to deploy projects to devices running iOS 11 or greater.

Using Legacy Javascript Confirm Dialog:
x={
  onButtonPress: function() {
    var changes = { "standardConfirmStatus": "Waiting for user to close confirm dialog." };
    if (confirm('A question displayed using legacy confirm().Do you want to confirm or cancel?')) {
      changes = { "standardConfirmStatus": "OK was pressed." };
    } else {
      changes = { "standardConfirmStatus": "Cancel was pressed." };
    }

    // NOTE: Standard javascript dialogs will pause javascript execution.
    // Any code after calling alert() or confirm() will only continue after the user has responded.
    return changes;
  }
}

Passing custom parameters through a confirm dialog

The new javascript confirm dialog has an optional parameter for you to pass in a dictionary of custom parameters. This can be useful for passing in data which can then be retrieved in the onConfirmClosed callback . You can then continue processing the data with the user's response to the confirm and then save any changes back to the session. This functionality is only available in the New Javascript Dialogs and is not available in the Legacy Javascript Dialogs.

This example is also available in the Javascript Sample Dialogs project which can be downloaded or imported into your account at the bottom of this page .

Description:

This example shows how custom parameters can be passed into a confirm dialog and then retrieved in the onAlertClosed callback . If the OK button is pressed, the confirm ID that is passed in as a custom parameter will be saved to the edit point called confirmIdentifier . If the Cancel button is pressed, the confirm ID will not be updated. The javascript is triggered when the Selection Point with ID fourfivesix changes value, using the onPointValueChanged callback .

This example demonstrates two ways of retrieving the value of the point that changed. The onPointValueChanged callback was updated to provide the pointValue parameter in version 1.1 of the javascript point.

Show example
x={
  onPointValueChanged: function(pointId, pointValue) {
    if(pointId == "fourfivesix") {
       var isLegacyVersion = false;
       if(typeof javascriptVersion === "undefined" || javascriptVersion < 1.1) {
          // Legacy support
          // Version 1.1 added the pointValue parameter to the onPointValueChanged callback.
          // If using an older version of the app with an older javascript version, retreive
          // the pointValue the another way.
          isLegacyVersion = true;
          pointValue = this.project.session['fourfivesix'];
       }

       if (!pointValue) {
          // If the value is empty, undefined, null, untruthy... don't show an alert.
          return { "confirmWithIdentifierStatus": "Deselected.", "confirmIdentifier": "" };
       }

       var customParameters = { "myConfirmId": pointValue };
       if (isLegacyVersion) {
         return { "confirmWithIdentifierStatus":"Update the Mobile Data Anywhere app to use the new javascript alerts."};
       } else {
         this.confirmDialog("Confirm with ID:" + pointValue, customParameters);
       }

       return;
    }
  },
  onConfirmClosed: function(response, customParameters) {
    var thisConfirmId = customParameters["myConfirmId"];
    if (response) {
      return {
        "confirmWithIdentifierStatus": "Confirmed id: " + thisConfirmId,
        "confirmIdentifier":thisConfirmId
      };
    } else {
      return { "confirmWithIdentifierStatus": "Cancelled id: " + thisConfirmId };
    }
  }
}

Javascript Callbacks

Javascript code can be executed by implementing a javascript callback within a Javascript point. The callbacks are triggered under various scenarios such as when a session is started or finished. The following callbacks are available. Please note that some callbacks and some callback parameters are only available on the most recent version of the Mobile Data Anywhere app. If you are unable to ensure all your devices are running the latest version of the app, please see the Javascript Versions and Availability section.

Available Callbacks

Callback Usage Availability
onButtonPress onButtonPress() 1.0
onSessionStart onSessionStart() 1.0
onSessionFinish onSessionFinish() 1.0
onProjectDatabaseChanged onProjectDatabaseChanged(project) 1.0
onPointValueChanged onPointValueChanged(pointId) 1.0
onPointValueChanged(pointId, pointValue) 1.1
onAlertClosed onAlertClosed(customParameters) 1.1
onConfirmClosed onConfirmClosed(response, customParameters) 1.1

onButtonPress

The onButtonPress function will only be executed if the javascript point’s display mode is set to Just a Button which will display a button on the screen, on the mobile application. When this button is pressed, the onButtonPress function will be executed.

Usage Availability
onButtonPress() 1.0
Show example
x={
  onButtonPress: function()
  {
      var changes = {};

      // Setup a variable to store the number of times the
      // button is pressed.
      if (window.pressedCount == null) {
          window.pressedCount = 0;
      }
      // Each time this button is pressed, we increment the count by one.
      window.pressedCount = window.pressedCount + 1;

      // Update EditPoint1's value with a message.
      changes['EditPoint1'] = "Pressed " + window.pressedCount + " times.";
      return changes;
  }
}

onSessionStart

The onSessionStart function will be executed when a new session is created.

Usage Availability
onSessionStart() 1.0
Show example
x={
  onSessionStart: function()
  {
    var changes = {};
    changes['EditPoint1'] = "A new session has started!";
    return changes;
  }
}

onSessionFinish

This function will be executed when a new or edited session is finished.

Usage Availability
onSessionFinish() 1.0
Show example
x={
  onSessionFinish: function()
  {
    var changes = {};
    changes['EditPoint1'] = "A new session was finished!";
    return changes;
  }
}

onProjectDatabaseChanged

This function will be executed when a project’s session list has changed. This includes changes such as a new session being finished or a session being sent, duplicated or deleted. This function has a parameter called project which will be the name of the project that was changed. This could be the currently open project or could be another project such as a sub project. The project parameter can be used to handle the event for specific projects.

Usage Availability
onProjectDatabaseChanged(project) 1.0

Parameters
Parameter Type Description Availability
project string The filename of the project that was updated. 1.0
Show example
x={
  onProjectDatabaseChanged: function(project)
  {
    var changes = {};
    changes['EditPoint1'] = "Project " + project + " was updated!";
    return changes;
  }
}

onPointValueChanged

This function will be executed when any point’s value is updated. This function has a parameter key which will be the ID of the point that changed. This parameter can be used to handle the event for specific points.

Usage Availability
onPointValueChanged(pointId) 1.0
onPointValueChanged(pointId, pointValue) 1.1

Parameters
Parameter Type Description Availability
pointId string The ID of the point that was updated. 1.0
pointValue string The new value of the point that was updated. 1.1
Show example
x={
  onPointValueChanged: function(pointId, pointValue) {
    if(typeof javascriptVersion === "undefined" || javascriptVersion < 1.1) {
      // Legacy support: pointValue will be undefined for javascript versions prior to 1.1
      pointValue = this.project.session[pointId];
    }

    var newValueForEditPoint1 = "Point " + pointId + " has been updated with new value: " + pointValue;
    return { 'EditPoint1': newValueForEditPoint1 };
  }
}

onAlertClosed

This function will execute when an alert dialog is closed. This will not occur if using the legacy javascript alert dialogs which are no longer supported.

Usage Availability
onAlertClosed(customParameters) 1.1

Parameters
Parameter Type Description Availability
customParameters {} When a javascript alert is presented using the new javascript alert dialog, this.alertDialog(message, customParameters) the customParameters will be passed through to this callback when the user closes the alert. 1.1
Show example
onAlertClosed: function(customParameters) {
  var aCustomParameter = customParameters["aCustomParameter"];
  var changes = {};
  changes['EditPoint1'] = "An alert closed with custom parameter " + aCustomParameter;
  return changes;
}

onConfirmClosed

This function will execute when a confirm dialog is closed. This will not occur if using the legacy javascript confirm dialogs which are no longer supported.

Usage Availability
onConfirmClosed(response, customParameters) 1.1

Parameters
Parameter Type Description Availability
response boolean When a user closes a javascript confirm dialog this response will be true if the user pressed the OK button and will be false if the user pressed the Cancel button. 1.1
customParameters {} When a javascript confirm is presented using the new javascript confirm dialog, this.confirmDialog(message, customParameters) the customParameters will be passed through to this callback when the user closes the confirm. 1.1
Show example
onConfirmClosed: function(response, customParameters) {
  var aCustomParameter = customParameters["aCustomParameter"];
  var changes = {};
  if (response) {
    changes['EditPoint1'] = "An alert closed with custom parameter " + aCustomParameter;
  } else {
    // User cancelled the dialog so don't make any changes to the session.
  }
  return changes;
}

Retrieving session summaries

A session summary is stored for each session on the device and can be retrieved from within javascript code. This process starts by getting a reference to the project, using the project's full file name, and then retrieving the summaries from the project.

Session summaries do not contain all custom point values, as this would cause performance issues on most mobile devices. Instead, the summary contains a set of base data as well as values for each point that has been specified in the project's session list columns.

Show basic example
Basic example of how to retrieve session summaries:
x={
  onButtonPress: function()
  {
      // Get the guid of the currently open session.
      var sessionGuid = this.project.session.__guid__;

      // Get a list of session summaries from the sub project.
      var childProject = projects['JavascriptPushDataChild.ppc'];
      var summaries = childProject.summaries;

      // ... use session summaries
  }
}
Show example: Sorting by saved timestamp (descending)

Sorting by saved timestamp (descending):
x={
  onButtonPress: function() {
    var childProject = projects['JSLastChildSubproject.ppc'];
    var summaries = childProject.summaries;
    var sessionGuid = this.project.session.__guid__;

    var sortedChildren = '';

    // Filter to non-deleted, related child sessions
    summaries = summaries.filter(function(el) {
        return (el.parent_guid)
          && (el.parent_guid.toUpperCase() == sessionGuid.toUpperCase())
          && (el.status != 2);
    });

    // Sorting
    var sortedChildSessions = summaries.sort(function(a, b) {
        if(a.saved_timestamp === b.saved_timestamp) {
            return a;
        } else {
            return b.saved_timestamp - a.saved_timestamp;   // Descending
        }
    });
    var lastChildGuid = sortedChildSessions[0].guid;    // Most recent

    for(childSession in sortedChildSessions) {
        var summary = sortedChildSessions[childSession];
        var childGuid = summary.guid;
        var savedDate = summary.saved;
        var guidPrefix = childGuid.substring(0,8);
        sortedChildren += savedDate + ": " + guidPrefix + "
"; } return { 'sorted_children': sortedChildren, 'most_recent_child': lastChildGuid }; } }
Show example: Sorting by saved timestamp (ascending)

Sorting by saved timestamp (ascending):
x={
  onButtonPress: function() {
    var childProject = projects['JSLastChildSubproject.ppc'];
    var summaries = childProject.summaries;
    var sessionGuid = this.project.session.__guid__;
    var sortedChildren = '';

    // Filter to non-deleted, related child sessions
    summaries = summaries.filter(function(el) {
        return (el.parent_guid)
          && (el.parent_guid.toUpperCase() == sessionGuid.toUpperCase())
          && (el.status != 2);
    });

    // Sorting
    var sortedChildSessions = summaries.sort(function(a, b) {
        if(a.saved_timestamp === b.saved_timestamp) {
            return a;
        } else {
            return a.saved_timestamp - b.saved_timestamp;   // Ascending
        }
    });
    var lastChildGuid = sortedChildSessions[sortedChildSessions.length - 1].guid;   // Most Recent

    for(childSession in sortedChildSessions) {
        var summary = sortedChildSessions[childSession];
        var childGuid = summary.guid;
        var savedDate = summary.saved;
        var guidPrefix = childGuid.substring(0,8);
        sortedChildren += savedDate + ": " + guidPrefix + "
"; } return { 'sorted_children': sortedChildren, 'most_recent_child': lastChildGuid }; } }

Saving changes to session

Javascript callbacks can be used to save changes to the currently open session and since javascript version 1.2, changes can be persisted to any session on the device.


Saving to the open session

When a callback is executed and a dictionary (hash table) is returned, the keys will be used to find points within the currently open session. If a point is found then the value for the matching key will be saved to the session. See below for an example:

Show example
x={
  onButtonPress: function()
  {
      var changes = {};

      // This will save the value 'Example' to the point named 'EditPoint1'
      changes['EditPoint1'] = "Example";

      // This will save the value 45.32 to the point named 'NumpadPoint1'
      changes['NumpadPoint1'] = 45.32;

      return changes;
  }
}
Or more concisely:
x={
  onButtonPress: function()
  {
      return {
        'EditPoint1': 'Example',
        'NumpadPoint1': 45.32
      };
  }
}

Saving to multiple sessions

Javascript version 1.2 introduced the ability update multiple sessions, including session from other projects. This can be done by returning an array that contains a dictionary (hash table) per project.

Show basic example
Basic example of how to save data for two sessions that belong to the project, "JavascriptPushDataChild.ppc" as well as a session from the "JavascriptPushDataParent.ppc" project. See the next example for how to retrieve the guids for parent and sub sessions instead of hard-coding values.
x={
  onButtonPress: function()
  {
    return [
      {
        'project.path': 'JavascriptPushDataChild.ppc',
        'sessions': {
          'ff7f9262-4d55-42a1-8113-573f0d937ace': {
            'EditPoint1': 'Example'
            'NumpadPoint1': 45.32
          },
          '4ded65b0-5b9e-43f1-ba4f-e836e904b40b': {
            'EditPoint1': 'Example',
            'NumpadPoint1': 45.32
          },
        }
      },
      {
        'project.path': 'JavascriptPushDataParent.ppc',
        'sessions': {
          '5f423a2f-6c94-4aa9-b749-beb9538f819b': {
            'EditPoint1': 'Example'
            'NumpadPoint1': 45.32
          },
        }
      }
    ];
  }
}
Show advanced example

Example of how javascript can be used with the Sub Project point to save data to all sub sessions as well as the opened parent session.
x={
  onButtonPress: function()
  {
    // Get the guid of the currently open parent session.
    var sessionGuid = this.project.session.__guid__;

    // Get a list of session summaries from the sub project.
    var childProject = projects['JavascriptPushDataChild.ppc'];
    var summaries = childProject.summaries;

    // Filter the sub sessions to only include sessions that are related to the open parent session.
    // This is determined by comparing each sub session's 'parent_guid' with the guid of the opened
    // session.
    // This will also filter out any deleted sessions by ensuring each sub session does not have
    // a deleted status (status of 2).
    var childSessions = summaries.filter(function(el) {
        return (el.parent_guid)
          && (el.parent_guid.toUpperCase() == sessionGuid.toUpperCase())
          && (el.status != 2);
    });

    // Loop through the related sub sessions and prepare a dictionary containing the changes to
    // be applied.
    var childSessionsData = {};
    for(childSession in childSessions) {
        var childGuid = childSessions[childSession].guid;
        childSessionsData[childGuid] = { 'parent_data': 'Data from parent session ' + sessionGuid };
    }

    // Prepare a dictionary to define the sub project and the sessions to update.
    var childProjectChanges = {
        'project.path': 'JavascriptPushDataChild.ppc',
        'sessions': childSessionsData
    }

    // Prepare a dictionary to define the parent project and the session to update.
    var statusMessage = new Date().toLocaleString() + ': Pushed to ' + childSessions.length + ' children.';
    var parentProjectChanges = {
        'project.path': 'JavascriptPushDataParent.ppc',
        'sessions': {
            [sessionGuid]: { 'status': statusMessage }
        }
    }

    // Returning an array, containing a dictionary per project.
    return [ childProjectChanges, parentProjectChanges ];
  }
}

Showing/Hiding points using Javascript

Similar to the Logic point , javascript is able to show and hide points in the current session. This can help improve the maintainability of large projects where Logic points are used extensively to show and hide points. Instead, this can now be maintained in a single Javascript point.

If both a Logic point and a Javascript point are used to show/hide the same point, whichever is evaluated last will determine the outcome. It is recommended to use one or the other to avoid any confusion when maintaining your project.

Most points can be shown/hidden using a reference to the point's name. However, the Layout point does not have a point name and instead can be referenced using the text content.

Show example: Showing points

Example of how to show 3 points using javascript:

  • An Edit point, referenced using the point name 'Edit'
  • A Layout point, referenced using the text content 'This layout will appear/disappear.'
  • A Boolean point, referenced using the point name 'boolean'
x={
  onButtonPress: function() {
    this.showPoints(['Edit', 'This layout will appear/disappear.', 'boolean']);
  }
}
Show example: Hiding points

Example of how to hide 3 points using javascript.

  • An Edit point, referenced using the point name 'Edit'
  • A Layout point, referenced using the text content 'This layout will appear/disappear.'
  • A Boolean point, referenced using the point name 'boolean'
x={
  onButtonPress: function() {
    this.hidePoints(['Edit', 'This layout will appear/disappear.', 'boolean']);
  }
}

Helper Functions and Global Variables

There are several functions and variables that are available within javascript that can be used to process session data and assist with debugging issues with your javascript code.

Functions

Function Description Availability
printObject(object) Can be used to print an object's properties to console log where the standard console log for a cyclic object would otherwise fail. 1.1

Global Variables

Variable Description Availability
javascriptVersion If defined will return the Float value of the javascript version that is available on the device.

Will not be defined on versions prior to 1.1. Supporting earlier versions requires:
if (typeof javascriptVersion !== "undefined" && javascriptVersion >= 1.1) { ... }
1.1
systemPlatform If defined will return the String value of "iOS" or "Android" representing the device's platform. This can be used to handle javascript code separately per platform.

Will not be defined on versions prior to 1.1. Supporting earlier versions requires:
if (typeof systemPlatform !== "undefined") { ... }
1.1
deviceInformation If defined will return the Dictionary value containing information about the current device and installed version of the Mobile Data Anywhere app.
Show example
{
  'app': 'Mobile Data Anywhere 1.1.41/1166',
  'appName':'Mobile Data Anywhere',
  'appVersion':'1.1.41',
  'appBuild':'1166',
  'deviceModel':'iPhone',
  'deviceSystem':'iPhone OS',
  'deviceVersion':'11.1'
}

Will not be defined on versions prior to 1.1. Supporting earlier versions requires:
if (typeof deviceInformation !== "undefined") { ... }
1.1

Sample Projects

The following samples demonstrate how the Javascript Point can be used in several different ways, in your projects. Please start by downloading the project files and the javascript files that are used in these samples.


Sample Projects
You can download the sample files for this tutorial or import the projects directly into your account.

Sample 1: Javascript Button

This sample demonstrates how javascript code can be executed using the Button interface from a Javascript Point. Each time the button is pressed, a value is incremented and saved to an edit point.

The project contains an edit point, EditPoint1 , and has a javascript point called JavascriptPoint which has been configured with the properties seen below:


On button press

The Display Mode option has been set to Just a Button which will display a button within the session when used on a mobile device. The button will display the text “Press Me”.

The Javascript Code contains a function callback for onButtonPress which is executed when the javascript point’s button is pressed.

Each time the button is pressed, the javascript will increment a number and store this number as the pressedCount . By storing this value in window.pressedCount , this value is shared with all other projects and sessions. This function contains a dictionary called changes which is used to set a value for the edit point, EditPoint1.

var changes = {};

...

changes['EditPoint1'] = "The button has been pressed " + window.pressedCount + " times.";
return changes;

Sample 2: Javascript Callbacks

This sample demonstrates how javascript code can be executed using the various javascript callbacks that are available including; onPointValueChanged, onSessionStart, onSessionFinish, onProjectDatabaseChanged.

In the Javascript Sample project there is a javascript point called JavascriptCallbacks on page 2. This javascript point has been configured with the properties seen in the screenshot below and is described in more detail in the following section. The javascript code that is used for this point is included with the sample projects in a file, javascript_sample_2_callbacks.js .


Javascript point callbacks properties

OnSessionStart

The onSessionStart callback is executed whenever a session is started which includes starting a new session and starting an existing session.

onSessionStart: function() {
  // Ensure project storage has been initialised.
  if (window.projectstorage == null) {
    window.projectstorage = {};
  }

  var changes = {};

  // This is how you can determine if the session has just been created or if
  // the session is an existing session.
  if (this.project.session.__new__) {
    changes['onSessionStartNew'] = 'True'; // New session
  } else {
    changes['onSessionStartExisting'] = 'True'; // Existing session
  }

  return changes;
}

This callback is important as it is the first callback to be executed when opening a session and can be used to prepare anything that needs to be used in other callbacks. For example, in the sample this method prepares a dictionary window.projectstorage which will be used to store session-specific data.

// Ensure project storage has been initialised.
if (window.projectstorage == null) {
  window.projectstorage = {};
}

Javascript code can be used to determine the difference between starting a new session and an existing session using:

// This is how you can determine if the session has just been created or if
// the session is an existing session.
if (this.project.session.__new__) {
  changes['onSessionStartNew'] = 'True'; // New session
} else {
  changes['onSessionStartExisting'] = 'True'; // Existing session
}

OnSessionFinish

The function onSessionFinish is executed whenever a session is finished. In this sample, this function is used to increment a count of the times that the session has been finished. This sample demonstrates several important features of the Javascript Point including how to store data specifically for each session and how to create custom functions.

onSessionFinish: function() {
  var changes = {};

  // Increment and store the finishedCount.
  var finishedCount = this.getValueForKey('finishedCount');
  finishedCount += 1;
  this.storeValueForKey('finishedCount', finishedCount);


  changes['onSessionFinish'] = finishedCount + ' times';
  return changes;
},
storeValueForKey: function(key, value) {
  var project = getProject('javascript_sample_2_callbacks.ppc');
  var sessionGuid = project.session.__guid__;

  // Ensure this session's storage has been initialised.
  if (window.projectstorage[sessionGuid] == null) {
    window.projectstorage[sessionGuid] = {};
  }

  window.projectstorage[sessionGuid][key] = value;
},
getValueForKey: function(key) {
  var project = getProject('javascript_sample_2_callbacks.ppc');
  var sessionGuid = project.session.__guid__;


  if (window.projectstorage != null) {
    if (window.projectstorage[sessionGuid] != null) {
      return window.projectstorage[sessionGuid][key];
    }
  }
  return null;
}

OnProjectDatabaseChanged

This function is used is useful when used in conjunction with a SubProject Point as this function will execute when a sub project’s database has been updated. This function is useful in doing calculations or post processing for the parent session, whenever a change is detected in the sub project. A sub project is updated when a session is created, sent, duplicated or deleted. It will also be triggered when the sub project’s session list is viewed.

onProjectDatabaseChanged: function(project) {
  var changes = {};
  changes['onProjectDatabaseChanged'] = 'True';
  return changes;
}

OnPointValueChanged

This function in the javascript code, onPointValueChanged , is executed whenever a point is updated within a session. Javascript code can be used to filter this action so that it only makes changes to your data when specific conditions are met.

onPointValueChanged: function(key) {
  var changes = {};

  // These changes will be applied when any point has changed value.
  changes['onPointValueChangedForAnyPoint'] = 'True';

  // Only update the display if the point that changed is not onPointValueChangedName.
  if (key != 'onpointvaluechangedname') {
    changes['onPointValueChangedName'] = key;
  }

  // Filter this function to only update the session when the point ChangeMe changes.
  if (this.project.session.changeme.length > 0) {
    changes['onPointValueChanged'] = 'True';
    changes['onPointValueChangedName'] = key;
  }

  return changes;
}

Sample 3: Javascript Session Data

This sample demonstrates how a Javascript point can be used to extract session values from a project and how to sort the session data. See the provided sample project, javascript_sample_session_data.ppc , for a full example.

Configuring Session List Columns

In order for a Javascript point to have access to session point values, each of the points need to be added to the project's Session List Columns. This can be configured in the designer by going to Project properties -> Options -> Session List Columns .

Retrieving session summaries

Once the points have been added to the Session List Columns, they become accessible in the project's list of session summaries.

Summaries for the Current Project
var sessionSummaries = this.project.summaries;
Summaries for a Different Project
var otherProjectFileName = 'other test project.ppc';
var otherProject = getProject(otherProjectFileName);
var otherSessionSummaries = this.project.summaries;
Example below is when the project contains one session:
[
  {
    "status":0,
    "values":{"selection1":"C", "startdate":"2021-01-05 10:11:22", "selection2":"X"},
    "parent_guid":null,
    "saved":"05-01-2021",
    "created":"05-01-2021",
    "guid":B4FF1D5C-A971-4FA5-9ED5-EB11C5FBC6F1",
    "saved_timestamp":1612498314,
    "created_timestamp":1612498307
  },
  ... additional sessions ...
]

Sorting session summaries

Sorting the summaries can be done using each summary's properties:
x = {
  onSessionStart: function()
  {
    var summaryPropertyName = 'saved';
    var sortByAscending = true;
    this.sortOnStringProperty(this.project.summaries, sortingPointName, sortByAscending);

    // ...
    // this.project.summaries is now sorted
    // ...
  },
  sortOnStringProperty(arr, property, asc = true) {
    arr.sort(function (a,b) {
      if(asc){
        return a[property].localeCompare(b[property]);
      }else{
        return b[property].localeCompare(a[property]);
      }
    });
  },
}
Sorting using a summary's value property:
x = {
  onSessionStart: function()
  {
    var sessionPointName = 'selection1';
    var sortByAscending = true;
    this.sortOnStringValueProperty(this.project.summaries, sortingPointName, sortByAscending);

    // ...
    // this.project.summaries is now sorted
    // ...
  },
  sortOnStringProperty(arr, property, asc = true) {
    arr.sort(function (a,b) {
      if(asc){
        return a[property].localeCompare(b[property]);
      }else{
        return b[property].localeCompare(a[property]);
      }
    });
  },
}
See the sample project, javascript_sample_session_data.ppc , for a full example.