JavaScript Functions

This page has not been liked. Updated 6/3/15, 8:49 AM by ChrisDawes(IBM)Tags: None

This section is dedicated to custom JavaScript functions that you can use within FEB.  Feel free to use these, or share your own!  Note that all of these functions are written with the assumption that the secureJS parameter in the Builder_config.properties is set to true, therefore some of the syntax looks different then if you were just writing natural, unhindered javascript.

You may also download all of the functions.

**All functions can be placed in Settings...Events...Custom Actions or in a file that you attach to the application.

Functions Table of Contents

Tables

Lists

Other

Dates
   

 

Functions

Sort a List

/*

* Will sort the options of the item passed to it.

* Must pass it the UI item reference.  If called from in the list object you can use "item",

* otherwise would have to use "page.F_DropDown" or "form.getPage('P_Page').F_DropDown"

*

* Will keep track of the currently selected value and insure that it is re-selected after the list is sorted

*/


app.getSharedData().sortList = function(theItem)

{

    //store the current value

    var value = theItem.getBOAttr().getValue();



     //sort the list

     var options = theItem.getOptions();



     if(options !== null) {

       options.sort(function(a,b) {

         return get(a, 'title').localeCompare(get(b, 'title'));

       });



       theItem.setOptions(options);



       //reset back to the current value

       theItem.getBOAttr().getValue(value);

     }

}

Description:

Sorts the content of the item that is passed to the function.  The function supports Dropdown, Select One and Select Many.  The function will overwrite the options of the item that is passed to it.  If the item has a selected value then that value will still be selected after the list is sorted.

Usage Notes

1. Copy the code to the Settings...Events...onStart section of your application.

2. There are several different ways in which you could use this function.  If the form item already contains the items you could add the function call to the onShow event of the list item you want to sort:

app.getSharedData().sortList(item);

In the case of an item where its choices are populated by a service call you may want to sort the list after the items are populated.  An example of this would be to setup a listener for when the service call is completed and then call this function passing in the UI reference to the list you want to sort, for example:

app.getSharedData().sortList(form.getPage('P_NewPage').F_DropDown);

**Note: If you are using 8.5 and you are loading your list choices using a service that calls another Forms Experience Builder Application then you can use the OrderBy input parameter to sort the list choices rather then using this JavaScript function.

If you are calling a service where the orderBy parameter is not available then it is best to call this service after the service completes by creating an onCallFinished listener, place the following code in the onLoad event of the form:

var srv = form.getServiceConfiguration('SC_theService');

srv.connectEvent("onCallFinished", function(success)

{

  if(success) {

   //change the F_DropDown to the ID of the object that you want to sort

  app.getSharedData().sortList(form.getPage('P_NewPage').F_DropDown);

  }

});

Calculate Working Days Between Dates

/* Returns the number of working dates between the two dates.

* includeWeekends - Pass true if you want to include weekends otherwise false.

*/


app.getSharedData().workingDaysBetweenDates = function(startDt, endDt, includeWeekends) {

    // Validate input

    if (endDt < startDt)

        return 0;



    // Calculate days between dates

    var millisecondsPerDay = 86400 * 1000; // Day in milliseconds

    startDt.setHours(0,0,0,1);  // Start just after midnight

    endDt.setHours(23,59,59,999);  // End just before midnight

    var diff = endDt.getTime() - startDt.getTime();  // Milliseconds between datetime objects    

    var days = Math.ceil(diff / millisecondsPerDay);   

    if(!includeWeekends) {

        // Subtract two weekend days for every week in between

        var weeks = Math.floor(days / 7);

        var days = days - (weeks * 2);



        // Handle special cases

        var startDay = startDt.getDay();

        var endDay = endDt.getDay();



        // Remove weekend not previously removed.   

        if (startDay - endDay > 1)        

            days = days - 2;     



        // Remove start day if span starts on Sunday but ends before Saturday

        if (startDay === 0 && endDay !== 6)

            days = days - 1  



        // Remove end day if span ends on Saturday but starts after Sunday

       if (endDay === 6 && startDay !== 0)

           days = days - 1  

    }



    return days;

}

Description:

Returns the number of calendar days between the two dates specified.  The function expects to receive date objects, not strings.

 

Usage Notes:

1. Copy the code to the Settings...Events...onStart section of your application.

2. We want to make sure that the result gets updated if the user changes either date field.  Therefore in your form of two date fields add the following to the onItemChange of both date fields:

var startDate = BO.F_Date.getValue();

var endDate = BO.F_Date0.getValue();

if(startDate !== null && startDate !== null) {   

  var days= app.getSharedData().workingDaysBetweenDates(startDate,endDate, true);

   BO.F_SingleLine.setValue(days);

}

This will insure that if either date field changes that the days between gets updated.  You will have to change the id references to match the fields on your form:

F_Date is the Start Date

F_Date0 is the End Date

F_SingleLine is the field that will hold the number of days returned from the function

Calculate Duration

 

/* Returns the number of hours from the two times provided
* startTime - Can be date, time or dateTime
* endTime - Can be date, time or dateTime
* rndHours - Round the result to the highest integer (hour). Values are true or false.
*/
app.getSharedData().calcDuration = function(startTime, endTime, rndHours) {  
  //convert to milliseconds
  var d1 = startTime.getTime();
  var d2 = endTime.getTime();  
  var diff = d2 - d1;
  var durHours = diff / 1000 / 60 / 60;
 
  if(rndHours) {
    Math.ceil(durHours);
  }
    
  return durHours;
}

Description:

This function can be used to calculate the duration between two times.  This function currently supports calculating the duration into hours and minutes.  You could further enhance this function to support months and years, but the output will always be rendered as a string representing the number of hours.

 

Usage Notes:

1. Copy the code to the Settings...Events...onStart section of your application.

2. To call the function, on the onItemChange of your date fields add:

     var dur = app.getSharedData().calcDuration(BO.F_Time.getValue(),

     BO.F_Time0.getValue(),true);

     BO.F_SingleLine.setValue(dur);

 

This approach takes just the time values, but you could create a different function that took the actual field objects and then you could add validation and error messages if your business case required it. 

For example, you could make sure the start time did not come after the end time.  You could also force either time to be within a specific window (i.e. 8-5).  By using the field objects as the parameters you could use the item.setValid() functions to set them invalid and show error text if the user entered an invalid value.

Verify Entered Date is After Today

/* Given the BO of a date field this function will validate that the entered date is

* after today.

* dateObj1 - the business object of the date field (i.e. BOA, BO.F_Date1)

* errorMsg - The message to display to the user when the field is set to invalid

*/


app.getSharedData().isDateAfterToday = function(dateObj1, errorMsg) {

    //get todays date, including the current time

    var today = new Date();       

    var d = dateObj1.getValue(); //get date from passed object

    
//set the time of the date to just before midnight

    d.setSeconds(59);

    d.setMinutes(59);

    d.setHours(23);



    //D1 MUST be less then today

    if(d < today) {

          dateObj1.setValid(false, errorMsg);

    } else {

      dateObj1.setValid(true, "");

    }

}

Description:

This function will set the date field to invalid if the entered date is not after today.

 

Usage Notes: 

1. Copy the code to the Settings...Events...onStart section of your application.

2. You can use this function in the date field itself or elsewhere.  You could use this in the onItemChange event of the date field by:

    app.getSharedData().isDateAfterToday(BOA, "The date must be after today.");

Or you could use this in a different event within a different item:

    app.getSharedData().isDateAfterToday(BO.F_Date1, "The date must be after today.");

 

Compare Date Fields (D2 must be greater than D1)

/* Given two date fields the function will validate that they are numOfDays apart.

* If the dateObj2 is not numOfDays greater than dateObj1 then dateObj2 will be set

* invalid with the specified errorMsg.

*

* dateObj1 - the first date field (e.g. BO.F_Date1)

* dateObj2 - the second date field (e.g. BO.F_Date2)

* numOfDays - the number of days that D2 must be grater than D1

* errorMsg - The error message to display for D2 when invalid

*

* Usage: Place function in the Settings...onStart

* Call the function in the onItemChange of the two date fields:

* app.getSharedData().compareDatesByDays(BO.F_Date2, BO.F_Date3, 14, "The date must be 14 days past D1.");

*/

app.getSharedData().compareDatesByDays = function(dateObj1, dateObj2, numOfDays, errorMsg) {
 
var d1 = dateObj1.getValue(); //get first date 
var d2 = dateObj2.getValue(); //get sec date
var diff = 0;
 
//convert to milliseconds
var d1_milli = d1.getTime();
var d2_milli = d2.getTime();
 
//get difference and convert back to days
var diff_milli = d2_milli - d1_milli;
var nDays = Math.ceil(diff_milli / 1000 / 60 / 60 / 24);
 
  //if the diff is less then numOfDays set the d2 field invalid
  if(nDays < numOfDays) {
    dateObj2.setValid(false, errorMsg);
  } else {
    dateObj2.setValid(true, "");
  }
}

Description:

Given two dates the function will validate that they are numOfDays days apart.  If the dateObj2 is not numOfDays days greater than dateObj1 then dateObj2 will be set invalid with the specified errorMsg.

 

Usage Notes:

1. Copy the code to the Settings...Events...onStart section of your application.

2. Then in both of your date fields place this in the onItemChange event to

call the function (make sure you replace F_Date2 and F_Date3 with the IDs of your date fields):

app.getSharedData().compareDatesByDays(BO.F_Date2, BO.F_Date3, 14, "The date must be 14 days past D1.");

Remove Duplicates From List

app.getSharedData().removeDuplicatesFromList = function(theList) {



    var newList = new Array();

    //loop through the current list

  for(var j=0; j<theList.length;j++) {

      var curItem = get(theList, j);

      var itemFound = false;

      //loop through the newList checking to see if the item is there

      for(var k=0; k<newList.length;k++) {

        if(get(curItem, 'title') === get(get(newList, k), 'title')) {

         itemFound = true;

        break;

        }

      } 

      if(!itemFound) {

          newList.push(curItem);

      }

  }

  return newList;

}

Description:

This function will remove any duplicate options found the current set of options.

 

Usage Notes:

1. Copy the code to the Settings...Events...onStart section of your application.

2. Then you need to decide where and when to call the function.  In the case of a service call you would want to call it when the service completes.  Which might look something like this:

var service = form.getServiceConfiguration("SC_ServiceThatReturnsList");

  service.connectEvent('onCallFinished', function(success)

   {

    if(success) {          

       var cList = form.getPage('P_thePage').F_DropDown2.getOptions();

       var nList = app.getSharedData().removeDuplicatesFromList(cList);

       form.getPage('P_thePage').F_DropDown2.setOptions(nList);

    }

});

I would place this listener into the onLoad event of the form.  This technique works for dropdowns, check and radio lists.

If you wanted to do this for a table you would have to change the process slightly.

Remove Blank Option From List

/*Removes the blank option from the list even if it is not the first,

* will also remove any duplicate blank options

*

* theList - the List item from which to remove blank options

*

* returns a new list with no blank options

*/


app.getSharedData().removeBlankFromList = function(theList) {

  //check all options for a blank value and remove it...

  var newList = new Array();

  //loop through the current list

  for(var j=0; j<theList.length;j++) {

      var curItem = get(theList, j);

      if(curItem !== "") {

          newList.push(curItem);

      }

  }

  return newList;

}

Description:

Returns a new List that does not contain the blank value.  Supports Select One, Select Many and Dropdown objects.

Usage Notes:

1. Copy the code to the Settings...Events...onStart section of your application.

2. In the onShow event of the list object that you want to change call the function by doing something like:

   //get the dropdown options  

   var c_opts = form.getPage('P_NewPage').F_DropDown.getOptions();

   var n_opts = app.getSharedData().removeBlankFromList(opts);

   form.getPage('P_NewPage').F_DropDown.setOptions(n_opts);

This gets the existing list options, passes it to the function which returns a new list.  That new list is then set into the list object.

Check Table for Entry

/* check to see if entry exists in the table, this will check all rows and columns

table: This is the actual table object, not the string ID (e.g. BO.F_Table)

entry: this is the value of what you want to search for, the content of the table column will be converted to a string

usage: This is usually called within the onClick of a button that adds rows to a table.  Or you might want to search to see if a record exists in the table.

*   if(!app.getSharedData().checkTableForEntry(BO.F_Table, theSearchValue)) {

*          . . .

*   }

*/

app.getSharedData().checkTableForEntry = function(table, entry) {

  var entryFound = false;

  for(var i = 0; i < table.getLength(); i++) {

      var row = table.get(i);

      var tmpentry = entry;



      //loop through all the columns of the source table

      var cols = row.getChildren();

      for(var j=0;j<cols.getLength();j++) {

          var c = cols.get(j).getValue();

          //Convert to string for comparison

          if (cols.get(j).getType() !== "string") {

              c = c.toString();

           }



          if(c === tmpentry) {

            entryFound = true;

            break;

          }

        } //inner for 

      } //outer for

  return entryFound;

}

Description:

Checks to see if the specified text exists anywhere (any cell, any row) within the table. If the string is found then the function returns true, otherwise false.

This is a really helpful function if you want to determine available features based on the existence of an item within a table.  For example, you might want to make sure that a user can only enter text into the table once.  This function would enable you to provide that functionality. 

 

Usage Notes:

1. Copy the code to the Settings...Events...onStart section of your application.

2. This type of feature is typically called within the onClick event of a button that adds a row to the table.

  var entryFound = false;

  entryFound = app.getSharedData().checkTableForEntry(BO.F_Table, "IBM Forms");

 

or

  if(!app.getSharedData().checkTableForEntry(BO.F_Table, theSearchValue)) {

     //the string was NOT found in the table, so now do something!

   }

Check Table for Entry By Column

/* check to see if entry exists in the table, checks only the specified column

table: This is the actual table object, not the string ID (e.g. BO.F_Table)

column: This is the string of the columnID that you want to seach

entry: this is the value of what you want to search for, the data type should match that of the column you are searching (i.e. string, int, date)

*/

app.getSharedData().checkTableForEntry= function(tablecolumnentry) {

  var entryFound = false;

  for(var i = 0; i < table.getLength(); i++) {

    if(get(table.get(i),column).getValue() === entry) {

      entryFound = true;

      break;

    }

  }



  return entryFound;

}

Description:

This function checks a specific column of a table for the specified string.  If the string is found then the function returns true, otherwise false.

 

Usage Notes:

1. Copy the code to the Settings...Events...onStart section of your application.

2. To use this function you need to decide where and how you want to check the value that the user might be trying to add.

When you call the function you would use the following statement:

app.getSharedData().checkTableForEntry(BO.F_theTableObj, 'F_theColumnToSearch', 'theValueYouAreSearchingFor');

Count Table Rows that Contain Entry By Column

/* Count the number of times that entry exists in the table, checks only the specified column
* table: This is the actual table object, not the string ID (e.g. BO.F_Table)
* column: This is the string of the columnID that you want to seach
* entry: this is the value of what you want to search for, the data type should match that of the column you are searching (i.e. string, int, date)
*/
app.getSharedData().countTableRowsForEntry= function(table, column, entry) {
  var entryFoundCount = 0;
  for(var i = 0; i < table.getLength(); i++) {
    if(get(table.get(i),column).getValue() === entry) {
      entryFoundCount++;
    }
  }
  return entryFoundCount;
}

Description:

Returns the number of rows that contain the specified entry.

 

Usage Notes:

1. Copy the code to the Settings...Events...onStart section of your application.
2. To use this function you need to decide where and how you want to check the value that the user might be trying to add.
When you call the function you would use the following statement:
  app.getSharedData().countTableRowsForEntry(BO.F_theTableObj,     'F_theColumnToSearch', 'theValueYouAreSearchingFor');

Calculate Sum of ColumnA Where ColumnB Meets Specified Criteria

/*

* Returns the sum of columnA for all the rows where columnB matches the specified entry.

* For example: Sum all the 'currency fields' in the rows where dropdown = 'approved'

*

* table - pass the table object - BO.F_Table

* columnA - the string ID of the field to be part of the summation

* columnB - the string ID of the field used to determine if the row should be included

* entry - the string value to compare against columnB

*/


app.getSharedData().sumColumnA_searchByColumnB = function(table, columnA, columnB, entry) {  

  var sum = 0;

  for(var i = 0; i < table.getLength(); i++) {

    if(get(table.get(i),columnB).getValue() === entry) {

      sum += parseInt(get(table.get(i),columnA).getValue());

    }

  }

  return sum;

}

Description:

Returns the sum of columnA for all the rows where columnB matches the specified entry.









For example: Sum all the 'currency fields' in the rows where dropdown = 'approved'

 

Usage: 

1. Copy the code to the Settings...Events...onStart section of your application.

2. This function assumes that you are trying to sum a set of rows of a table where a field in those rows meets a specified criteria.  Copy the function into the Settings...Events section of your application.

To use this function you will need to place the following in the onShow event of the field where the sum is being shown, as well as the onAdd and onRemove events of the table:

BO.F_Currency4.setValue(app.getSharedData().sumColumnA_searchByColumnB(BO.F_Table, 'F_Currency', 'F_DropDown4', 'Approved'));

Copy Table Contents to another Table

/**

* Copy all the rows from one table to another.  This assumes that the tables have

* the same number of rows and it will copy the columns in order.  There is no error

* checking so if you try to copy a datatype that does not match it may throw a runtime error.

*

* sourceTable - The table object you want to copy (e.g. BO.F_Table)

* targetTable - The table object you want to copy into (e.g. BO.F_Table1)

* clearTable - true/false - If true will empty the target table before copying.

*

* USAGE: In the event where you want to trigger the function place code like:

*            app.getSharedData().copyRowsToAnotherTable(BO.F_Table, BO.F_Table0, true);

*/


app.getSharedData().copyRowsToAnotherTable = function(sourceTable, targetTable, clearTable) {

    if(clearTable) {

        targetTable.setValue(new Array());

    }



  for(var i = 0; i < sourceTable.getLength(); i++) {

      var row = sourceTable.get(i);

      var newRow = targetTable.createNew();



      //loop through all the columns of the source table

      var cols = row.getChildren();

      for(var j=0;j<cols.getLength();j++) {

          //get the row object of the target table

          var newCols = newRow.getChildren();



          //for each row of the source table we set the value into the same row of the target table

          newCols.get(j).setValue(cols.get(j).getValue());

      }

        targetTable.add(newRow);

  }

}

 

Move a Table Row Up One Position

/* Change the order of the table by moving a row up one position.

*

* theTable: the BO object of the table

* theRow: the BO object of the row to be moved

*

* usage: Place in a button's onClick event:

*   app.getSharedData().moveSelectionUp(BO.F_InputParameters, page.F_InputParameters.getSelection())

*   page.F_InputParameters.setSelection(-1);

*

* Clearing the selection after moving a row is critical otherwise errors may insue.

*/


app.getSharedData().moveSelectionUp = function(theTable, theRow) {

    var rowObjs = new Array();

    var rowMoved = false;



    //remove all rows from the table

    //store each row in a separate array


    while(theTable.getLength() > 0) {

        rowObjs.push(theTable.get(0));

        theTable.remove(theTable.get(0));

    }

    for(var i = 0; i < rowObjs.length; i++) {

        var firstRow = get(rowObjs, i);

        var secondRow = get(rowObjs, i+1); 



        if(!rowMoved) {

            if(secondRow === theRow) {

                //add second row first, then the current row

                theTable.add(secondRow);

                i++; //increment counter again because we just processed two rows in one loop

                rowMoved = true;

            }

        }

        theTable.add(firstRow);

    }

}

 

Move a Table Row Down One Position

/* Change the order of the table by moving a row down one position.

*

* theTable: the BO object of the table

* theRow: the BO object of the row to be moved

*

* usage: Place in a button's onClick event:

*   app.getSharedData().moveSelectionDown(BO.F_InputParameters, page.F_InputParameters.getSelection())

*   page.F_InputParameters.setSelection(-1);

*

* Clearing the selection after moving a row is critical otherwise errors may insue.

*/


app.getSharedData().moveSelectionDown = function(theTable, theRow) {

    var rowObjs = new Array();

    var rowMoved = false;

    //remove all rows from the table

    //store each row in a separate array


    while(theTable.getLength() > 0) {

        rowObjs.push(theTable.get(0));

        theTable.remove(theTable.get(0));

    }

    for(var i = 0; i < rowObjs.length; i++) {

        var firstRow = get(rowObjs, i);

        // check to make sure we are not the last row, if we are just put the row back in the table
        if(i < rowObjs.length - 1) {

          var secondRow = get(rowObjs, i+1);



          if(!rowMoved) {



            if(firstRow === theRow) {

                //add second row, then the current row

                theTable.add(secondRow);

                i++; //increment counter again because we just processed two rows in one loop

                rowMoved = true;

            }

          }

        }

        theTable.add(firstRow);

    }

}

 

Print The Contents of a Table

 

/* prints all the columns of the table */
  app.getSharedData().printTable = function(table) {
var s = "<p>"; //can change your html properties here
 
  //loop through all the table rows
  for(var i = 0; i < table.getLength(); i++) {
    var row = table.get(i); //get the first row
    var ol = row.getChildren(); //get the list object that contains the row fields
    for(var j=0;j<ol.getLength();j++) {
     var f = ol.get(j);
     var v = f.getValue();
     s += f.getID() + ": " + v + "<BR />"; //this controls the formatting of each column in the table row
    }
    s += "<BR /><BR />"; //this controls what happens when we move to the next row
  }
  s += "</p>"; //close the html elements that were started at the beginning
  return s;
}

Description:

Added: 2015-03-12

I created this function because I wanted a quick way to render the content of a table, that comes back from a service call, in a pure text format.  This is an iterative function that walks all the rows and columns of a table and converts its content to a string.  This is just an example of the type of thing that could be accomplished.  Ideally you would take the premise and expand it for your situation.  You may want to add more detailed html or css to really fine-tune what the printed result looks like.

 

Usage:

The most common use case would use this function to display the table content in an HTML Area so that you can apply your own custom HTML to provide the most detailed formatting.  You could also place the content in a Text item but you would not have any control over the formatting (i.e. applying bold, italic, etc).

If you are using this as I did, where a service populates a table then you will want to do the processing after the service completes, something like:

var srv = form.getServiceConfiguration('SC_ServiceConfig0');
srv.connectEvent("onCallFinished", function(success)
{
  if(success) {
    form.getPage('P_NewPage').F_HTMLArea.setContent(app.getSharedData().printTable(BO.F_Table1));
  }
});

There are a few things I should mention:

1. As of 8.6.0 there is no way to get the title of a field using the JS API and so I resort to giving each field an id that matches its content.  If I wanted I could then further modify my JS function to change the output based on the ID found, this is not ideal and we are adding JS functions to get field titles in a future version.

2. You can modify the function in any way to add your own HTML or css references to "beautify" the content.  Here is an image of me using the function in one of my sample apps (that also happens to ask our dear friend Watson about the location of "Sleepy Hollow"!)...

Randomize List Choices

/** Returns a random number between the numbers specified. */

app.getSharedData().randomFromInterval = function(from,to) {

    return Math.floor(Math.random()*(to-from+1)+from);

}

 

/** Randomizes the selections of the specified list item.

*  usage: in the onShow event of the list you want to randomize place: app.getSharedData().randomList(item);

*/

app.getSharedData().randomList = function(theItem) {

    //store the current value

    var value = theItem.getBOAttr().getValue();



     //set up the arrays

     var arrOptions = theItem.getOptions();

     var tmpOptions = theItem.getOptions();

     var newOptions = new Array();



     //Randomise the list

     if(arrOptions !== null) {

        for ( var i = 0; i < arrOptions.length; i++ ) {

           //the random number should be between 0 and the length of the array

           var j = app.getSharedData().randomFromInterval(0,tmpOptions.length-1);

           var temp = get(tmpOptions, j);



           //assign the item to the new array

           newOptions.push(temp);



           //remove the item from the temp array

           tmpOptions.splice(j, 1);

        }



        //Set the options back

        theItem.setOptions(newOptions);

        //reset back to the current value

        theItem.getBOAttr().getValue(value);

     }

}

 
 
Get Dropdown Title







/**

* Returns the Label of the dropdown item, searches by value

*/








app.getSharedData().getDropdownItemTitle = function(theList, compareValue) {

    var opts = theList.getOptions();

    var retVal = "";



    //loop all the items and return if you find the compareValue

    for(var i=0;i<opts.length;i++) {                

        var theItemBO = theList.getBOAttr();

        var theItemTitle = get(get(opts,i), 'title');

        var theItemValue = get(get(opts,i), 'value');



        if(theItemValue === theItemBO.getValue()) {

          retVal = theItemTitle;

              break;

        }

    }

  return retVal;

}

Description:

When you are using an ID for the saved value of a drop down and you need to get at the actual title.

 

Usage Notes:

1. Copy the code to the Settings...Events...onStart section of your application.

 Then to use it you would call it in the onItemChange of the dropdown:

    var selectedItemTitle = app.getSharedData().getDropdownItemTitle(item, BOA.getValue());



Then you can do whatever you want with the selectedItemTitle, like set it into another field:

    BO.F_SingleLine.setValue(selectedItemTitle);

Get Checklist Title

app.getSharedData().getCheckListItemTitles = function(theList, compareValue) {

   //split the compareValue into all the selected item

   var selChecks = compareValue.split("__#__");

   //for each one, get the title from the list and create a new concatenation

   var opts = theList.getOptions();

   var retVal = "";



   for(var h=0;h<selChecks.length;h++) {



        var v = get(selChecks, h);



        //loop all the items and return if you find the compareValue

        for(var i=0;i<opts.length;i++) {               

            var theItemTitle = get(get(opts,i), 'title');

            var theItemValue = get(get(opts,i), 'value');



            if(theItemValue === v) {

                if (retVal !== "") {

                  retVal += "__#__";

              }

              retVal += theItemTitle;

                  break;

            }

        }

      }

  return retVal;

}

Description:

Returns the displayed title of the checklist selection.  You pass it the value.

 

Usage:

 Then to use it you would call it in the onItemChange of the dropdown:



    var selectedItemTitle = app.getSharedData().getCheckListItemTitles(item, BOA.getValue());



Then you can do whatever you want with the selectedItemTitle, like set it into another field:



    BO.F_SingleLine.setValue(selectedItemTitle);

Validate Field By Pattern

app.getSharedData().validateByPattern = function(theItem, pattern, errMsg) {



  var re = new RegExp(pattern);



  if(!re.test(theItem.getValue())) {



    theItem.setValid(false, errMsg);



  } else {



    theItem.setValid(true, "");



  }



}

Description:

This function will enforce a regex pattern on the specified field and will set the field to invalid if it does not match.

 

Usage Notes:

For example, you may want to validate a single line field as a US based phone number. In the onItemChange event of the field you would place:

app.getSharedData().validateByPattern(BOA, /^\(\d{3}\) \d{3}-\d{4}$/, "The number provided does not meet the required format");

Pad Field Value

/* Returns the padded string.

* theVal - the string you want to pad

* padChar - the character you want to use to pad the string

* desiredLength - the total length the resulting string should be

*/ 

app.getSharedData.padValue = function(theVal, padChar, desiredLength) {
  while(theVal.length < desiredLength) {
    theVal = padChar + theVal;              
  }
  return theVal;
}

Description:

This function can be used to pad a string with a padding character up to a specified length.

 

Usage Notes:

Place this function in the onLoad event of the form.  Then in the onItemChange event of the field you wish to pad place:

BOA.setValue(app.getSharedData.padValue(BOA.getValue(), "0", 4));

This will pad the value with zeros up to a total string length of 4.

Constrain Field Data Length

Place this function in the Settings > Events

app.getSharedData().restrictFieldLength = function(theField, theLength) {
  var v = theField.getDisplayValue();
  if(v.length >= theLength) {
    theField.setDisplayValue(v.substr(0,theLength));
  }
}

Description:

This function will restrict the field length of a field.  It will not allow anymore characters to be entered into the field once the limit is reached.

 

Usage Notes:

Navigate to the field where you want to constrain the length.In the onItemLiveChange event place the code below.

app.getSharedData().restrictFieldLength(item, 3);

This will limit the length to (3). You can adjust this number according to your needs.

 

Recursive Function to Walk all Items in a Form

/*

* This is the function where you place the logic that you want to perform on the item that you are currently looking at.

* The recursive function passes the handle to the current item, from which you can then access any of its properties

*/

app.getSharedData().processItem = function(item) {

   //do whatever you want to the item...

    alert(item.getId() + " : " + item.getValue());

  //if(item.getType() === "text") {

    //do your thing

  //}

}

/*

* Returns true if the current item has children, otherwise false.

*/


app.getSharedData().hasItems = function(containerID) {

    var list = containerID.getChildren();

    if(list.getLength() > 0) {

     return true;

    } else {

        return false;

    }   

}

/*

* Recursive function used for counting form items.

* containerID: UI item (i.e. page or item)

* processItem: the function that contains the work we want to perform on the item we have accessed

*/


app.getSharedData().getItem = function(containerID, processItem) {

      var itemList;

      var pageList;

      var pageCount = 1;

      debugger;

      

      //check to see if the container is a form as it requires different processing

      if(containerID.getType() === "form") {

          pageList = containerID.getPageIds(); //list of the page IDs - not the actual objects!!

          pageCount = pageList.length;

      } else {

      itemList = containerID.getChildren();    

    }



    //need a loop to account for different pages

    for(var p=0; p<pageCount;p++) {

        if(containerID.getType() === "form") {

          itemList = containerID.getPage(get(pageList, p)).getChildren(); //get the page object from the form

        }

        

        //loop all the items

        for(var i=0; i<itemList.getLength(); i++)

        {

          var theItem = itemList.get(i);

          if(app.getSharedData().hasItems(theItem)) {

              //if container go into it...

                app.getSharedData().getItem(theItem, processItem);   

            } else {

                //other wise do something with the item

                if(dojo.isFunction(processItem)) { //make sure that the parameter passed is a function

                  processItem(theItem);        

                }

            }

        }

      }

}

Description:

Note: This function was modified on Feb 28, 2015 to a new 2.0 version!  I learned something new and wanted to make sure I shared it.  This function was not as generic as it could have been.  I recently encountered a scenario where I wanted to walk all the items in a container and perform action A and then walk all the items in a different container and perform action B.  With the old function I would have to create two copies of the function and replace the content in the else labelled "//otherwise do something".  With the power of JavaScript we can actually make it even more generic!  I have created a third function as part of this group called processItem.

 

UsageNotes:

If you have a need to walk all the items in a form and then perform some operation on each one, you could use these functions.  Place the functions in the Settings...Events...Custom Actions.  Then you can call the main function app.getSharedData().getItem(page) and it will iterate through all the objects on that page, including all the items within a container (section, tabbed folder).  Some examples of this function are:

Walk all the items in a form = app.getSharedData().getItem(form, app.getSharedData().processItem)

Walk all the items in a page = app.getSharedData().getItem(form.getPage('P_Page1'), app.getSharedData().processItem) //if you place in the form onLoad event you have to qualify the page

Walk all the items in a section = app.getSharedData().getItem(item, app.getSharedData().processItem) //if you place this in the onShow event of the section

Walk all the items in a tabbedFolder = app.getSharedData().getItem(form.getPage('P_Page1').F_TabbedFolder, app.getSharedData().processItem) //if you place this in the onLoad event of the form

 

If you wanted to only perform an operation on a specific item type then you could further modify the function:

if(item.getType() === "text") {

//do your thing

}

 

The item types are:

Item
Type
Item
Type
Attachment attachment Password password
Button button Single Line Entry text
Check Box checkBox Section section
Currency currency Select Many checkGroup
date date Select One radioGroup
Drop Down comboBox Survey survey
Email emailAddress Survey Question surveyQuestion
Folder Tab tabFolderTab Tabbed Folder tabFolder
HTML Fragment htmlArea Table aggregationListContainer
Image image Text richText
Media media Time time
Multi-Line Entry inputBox Time Stamp timeStamp
Number number Website webLink
Page page Web Link staticWebLink
Page Navigation pageNavigator    

Get Week Number From Date

/*
* Given the BO of a date field this function will return the week number the specified date
* is part of.
*
* theDt - the business object of the date field (i.e. BOA, BO.F_Date1)
*
* usage: In the onItemChange event of the date field 
*    app.getSharedData().getWeekNumberFromDate(BOA.getValue())
*/
app.getSharedData().getWeekNumberFromDate = function(theDt) {
 
if(theDt !== "") {
// Create a copy of this date object
var t = new Date(theDt);
// ISO week date weeks start on monday
// so correct the day number
var dayNr = (t.getDay() + 6) % 7;
 
// Set the target to the thursday of this week so the
// target date is in the right year
t.setDate(t.getDate() - dayNr + 3);
 
// ISO 8601 states that week 1 is the week
// with january 4th in it
var jan4 = new Date(t.getFullYear(), 0, 4);
 
// Number of days between target date and january 4th
var dayDiff = (t - jan4) / 86400000;
 
// Calculate week number: Week 1 (january 4th) plus the
// number of weeks between target date and january 4th
var weekNr = 1 + Math.ceil(dayDiff / 7);
 
return weekNr; 
} else {
return "";
}
}

Description:

 

Usage Notes:

Place the function in the onLoad event of the form where you want to use it.  Then in the date field where you want to get the week number, and say push the week number into another field, place the function

BO.F_weekNumber.setValue(app.getSharedData().getWeekNumberFromDate(BOA.getValue()));

Add Days To Date

/* Add number of days to a date.

* dateObj1 - The date field (i.e. BO.F_Date)

* numOfDays - The number of days to add

*/

app.getSharedData().addDaysToDate = function(dateObj1, numOfDays) {

    var d1 = dateObj1.getValue(); //get first date

    var d1_milli = d1.getTime();

    return new Date(Math.ceil(d1_milli + (1000 * 60 * 60 * 24 * numOfDays)));

}

Description:

 

Usage Notes: 

Place the function in the Settings...Events...Custom actions.  In the field where you enter the date or the number of days to add you place app.getSharedData().addDaysToDate(BO.F_Date, 90);

You can either hard-code the number of days to add or have the value come from a field.

Convert AD Date to Buddhist Date

/* Convert a standard AD date into a Buddhist Date

* dateAD: the date to convert

*

* usage: Place in onLoad or beforeSubmit event to convert a

* date.  The code would be something like:

*   BO.F_DATETIME.setValue(app.getSharedData().convertToBuddhistDate(new Date()));

*/


app.getSharedData().convertToBuddhistDate = function(dateAD){

    var dateBE = new Date(dateAD);

    dateBE.setFullYear(dateAD.getFullYear() + 543);

    return dateBE;

}

 

Calculate Age From Birth Date

/* Calculates the age from a specified birth date.

*

* birthDay - the date to calculate the age from

* returnAsInt - if true returns as a number, if false then a string

*

* usage: Place function in Settings...Events...Custom Actions

* BO.F_Number.setValue(app.getSharedData().getAgeFromBirthDate(BOA.getValue(), true));

* BO.F_SingleLine.setValue(app.getSharedData().getAgeFromBirthDate(BOA.getValue(), false));

*/


app.getSharedData().getAgeFromBirthDate = function(birthDay, returnAsInt) {

  //calculate age

  var today = new Date();

  var diff_sec = today.getTime() - birthDay.getTime();

  var age = diff_sec / 60 / 60 / 24 / 365 / 1000;

  var returnVal = "";

  //remove decimal

  age = age.toString();

  if(returnAsInt) {

    returnVal = parseInt(age.substr(0, age.indexOf(".")));

  } else {

    returnVal = age.substr(0, age.indexOf("."));

  }

  return returnVal;

}

 

Invalidate Field Based on Length

/*

* Function that can be used to check the content of a field and set it to invalid if it exceeds a specified length.

*Params:

* theItem - the UI object of the item to validate

* theLength - the max length of the field, if exceeded the field will be set to invalid

* theMsg - The text to render if the length is exceeded.

* usage:

*    - copy the entire function into the Settings...Events.

*    -  place in the onLiveItemChange event of the field to validate and change parameters as desired:

*       app.getSharedData().fieldLengthValidation(item, 3, 'Field will only accept 3 characters or less');

*/

app.getSharedData().fieldLengthValidation = function (theItem, theLength, theMsg) {

  var dval = theItem.getDisplayValue();



  if(dval.length > theLength) {

    theItem.getBOAttr().setValid(false, theMsg);

  } else {

    theItem.getBOAttr().setValid(true, '');

  }

}

Usage Notes:

- Place the function in the Settings...Events

- Use the function in the onLiveItemChange event of the field you want to validate

Calculate Sum of Fields

/*

* Returns the sum of all the fields specified

*

* fields - array of field objects - new Array(BO.F_Field1, BO.F_Field2, ...)

*/

app.getSharedData().sumFields = function(fields) {  

  var sum = 0;

  for(var i = 0; i < fields.length; i++) {

    var f = get(fields, i);

      if(f.getValue() !== "") {

        sum += parseInt(f.getValue());

      }

     }

 

  return sum;

}

Usage: Copy the function to Settings...Events section of your application.  Place this in the onShow event of the field where the sum is shown and then again in the onItemChange event of all the fields included in the summation:



BO.F_Sum.setValue(app.getSharedData().sumFields(new Array(BO.F_Field1, BO.F_Field2, BO.F_Field3, BO.F_Field4)));

This function assumes that the fields being provided are simple fields in your form, either String, Number or Curency.  This function is not suitable for creating the sum of fields in a table.

Get Month From Date

Added: 2015-03-12

Here is a function that when passed a date will return the month name.

/* Returns the Month name of the specified date.
*
* theDateField - pass it the date value like BO.F_Date.getValue()
*/
app.getSharedData().getMonthNameFromDate = function(theDateField) {
var month = theDateField.getMonth();
var monthName = "";
 
switch (month) {
case 0:
monthName = "January";
break;
case 1:
monthName = "February";
break;
case 2:
monthName = "March";
break;
case 3:
monthName = "April";
break;
case 4:
monthName = "May";
break;
case 5:
monthName = "June";
break;
case 6:
monthName = "July";
break;
case 7:
monthName = "August";
break;
case 8:
monthName = "September";
break;
case 9:
monthName = "October";
break;
case 10:
monthName = "November";
break;
case 11:
monthName = "December";
break;
}
 
return monthName;
}

Usage:

In the onClick event of a date field I can place the following to see the name of the month of the date selected.

alert(app.getSharedData().getMonthNameFromDate(BOA.getValue()));