• <GetStart>
  • CSPro User's Guide
    • The CSPro System
    • Data Dictionary Module
    • The CSPro Language
      • Introduction to CSPro Language
      • CSPro Program Structure
      • Programming Standards
      • Change Code Properties
      • Code Folding
      • Debugging CSPro Applications
      • Declaration Section
      • Procedural Sections
      • Logic
      • Language Elements
      • JavaScript Use in CSPro
        • Overview
        • JS Namespace
        • JS.eval Function
        • JS.invoke Function
        • JS.getValue Function
        • JS.getValueJson Function
        • JS.hasValue Function
        • JS.setValue Function
        • JS.setValueFromJson Function
        • JavaScript User-Defined Functions
        • CSPro ⇄ JavaScript Value Conversions
    • Data Entry Module
    • Batch Editing Applications
    • Tabulation Applications
    • Data Sources
    • CSPro Statements and Functions
    • Text Templates
    • Templated Reporting System
    • HTML, Markdown, and JavaScript Integration
    • Action Invoker
    • Appendix
  • <CSEntry>
  • <CSBatch>
  • <CSTab>
  • <DataManager>
  • <TextView>
  • <TblView>
  • <CSFreq>
  • <CSDeploy>
  • <CSPack>
  • <CSDiff>
  • <CSConcat>
  • <Excel2CSPro>
  • <CSExport>
  • <CSIndex>
  • <CSReFmt>
  • <CSSort>
  • <ParadataConcat>
  • <ParadataViewer>
  • <CSCode>
  • <CSDocument>
  • <CSView>
  • <CSWeb>

JavaScript User-Defined Functions

Executing JavaScript Functions From CSPro Logic
When incorporating JavaScript into a CSPro application, it is possible to create function wrappers in CSPro logic that appear as user-defined functions but call into JavaScript when invoked. To do this, use the declare keyword to declare the function, specifying its return type and parameters. Using the JS modifier after function indicates that the function will be found in JavaScript's global execution context, not in CSPro logic. For example:
declare function JS numeric dateDifferenceInDays(string dateFirst, string dateLast);
In CSPro logic, you can now write function calls as if this were a CSPro logic function, with any CSPro arguments converted to their JavaScript equivalents when the call is executed. If the JavaScript function returns a value, it is converted to the CSPro type specified in the function declaration. If the JavaScript function does not return a value, the CSPro function returns the default return value for user-defined functions (default or a blank string).
The JavaScript function's existence is not known until runtime. If the function does not exist when called, a runtime error is displayed and the function returns the default return value.
It is also possible to execute JavaScript functions using the JS.invoke function.
Executing CSPro Functions From JavaScript
CSPro logic user-defined functions can also be passed to JavaScript using the JS.invoke or JS.setValue functions.
When called from JavaScript, if the number of arguments is fewer than what the CSPro function requires, an exception is thrown. If too many arguments are provided, the additional arguments are ignored by CSPro. When the function is executed within the JavaScript environment, any arguments to the function are converted to their CSPro equivalents, with exceptions thrown when no conversion routine exists, or if the conversion failed.
The CSPro function's return value is converted to its JavaScript equivalent when the function terminates.
Example 1 (JavaScript Function Wrapper)
With the following JavaScript script added to the application...
function dateDifferenceInDays(dateFirst, dateLast) {
   
const millisecondsPerDay = 24 * 60 * 60 * 1000;
   
const dateDifference = new Date(dateLast) - new Date(dateFirst);
   
return Math.floor(dateDifference / millisecondsPerDay);
}
...it is possible to wrap it using declare and JS and execute it from CSPro logic:
PROC GLOBAL

declare function JS numeric dateDifferenceInDays(string dateFirst, string dateLast);

PROC DEMO

   
// execute the wrapped function as if it were a CSPro function
    errmsg("%d", dateDifferenceInDays("2000-11-07", "2024-11-05"));

   
// execute the JavaScript function using JS.invoke
    errmsg("%s", JS.invoke("dateDifferenceInDays", "2000-11-07", "2024-11-05"));

   
// execute the equivalent CSPro built-in function
    errmsg("%d", datediff(20001107, 20241105, "d"));
Example 2 (CSPro Function Execution Using JS.setValue)
This example uses JS.setValue to add a function to JavaScript that, when executed, calls into CSPro logic to call the accept function. The example uses JS.eval to show how this could be executed from within JavaScript:
PROC GLOBAL

function numeric ChooseOption(string heading, List string options)
   
exit accept(heading, options);
end;

PROC DEMO

   
JS.setValue("chooseOption", ChooseOption);

   
JS.eval("const options = [ 'Frequently', 'Sometimes', 'Never' ];"
           
"chooseOption('How often do you use this feature?', options);");
Example 3 (CSPro Function Execution Using JS.invoke)
CSPro logic user-defined functions can be used as arguments. With the following JavaScript script added to the application...
function getCSProVersion(diagnosticsCallback) {
   
return diagnosticsCallback("version");
}
...it is possible to call into JavaScript and then have JavaScript call back into CSPro.
function string ExecDiagnostics(string property)
   
exit diagnostics(property);
end;

JS.invoke("getCSProVersion", ExecDiagnostics)); // 8.1
diagnostics("version");                         // 8.1
See also: JavaScript Use in CSPro, CSPro ⇄ JavaScript Value Conversions