Top Javascript Fixes / Recipes

While Formstack for Salesforce out of the box is a wonderful form building tool, sometimes our users need a little more customization. No fear, with Javascript you can modify your form to suit your needs. Below are the top Javascript fixes our customers use.

Adding Javascript in Form Settings

While editing your form, click on the Form Settings button. Here, if you scroll down towards the bottom you can see a section called Javascript Code. Place the code listed below in the white box.

 

Publishing Your Form

Once you have pasted the code, the Form Settings will save automatically. Exit the Form Settings and click "Publish Draft" to publish your form. Your code will now be in place!

 

Javascript Recipes 

Picklist

Date

Field Formatting and Validation

Form Styling and Behavior

Pre-populating Fields

Picklist

Limit a multi-select picklist to 2 choices or fewer

By default, multi-select picklists allow you to select as many options as needed. If you want to limit these options, the code below will work! If you need a different number besides 4, simply replace the 4 with whatever number you need. 

var last_valid_selection = null;

function FF_OnAfterRender() {

document.getElementById("Contact.multi_select_test__c").addEventListener("change", function() {

if ($(this).val().length > 2) {

$(this).val(last_valid_selection);

}

else {

last_valid_selection = $(this).val();

}

});

};
 

Change "-Select an item-" on a picklist to something else.

Where you see YOURFIELDIDHERE is where you'll input the API name for the field you're working with Right click and inspect the field to get the ID. Where you see YOUR TEXT HERE is where you can enter a custom message in lieu of -Select an Item- 

function FF_OnAfterRender(){

jQuery("select[id*='YOURFIELDIDHERE']").find("option").each(function(){

    console.log(jQuery(this).val())

    if(jQuery(this).val() == ""){

        jQuery(this).text("YOUR TEXT HERE");

    }

});

}

Change "-Select an item-" on a picklist for all picklists on a form.

function FF_OnAfterRender(){

jQuery("select[class*='ff-select-type']").find("option").each(function(){

    console.log(jQuery(this).val())

    if(jQuery(this).val() == ""){

        jQuery(this).text("YOUR TEXT HERE");

    }

});

} 

Remove form section if pick list is a certain value

Sample javascript that will remove a section of a form if a picklist is equal to a certain value.

function FF_OnBeforeSave(){ 
if (document.getElementById('YourObject.YourFieldId').value === "YourPickListValue") {
document.getElementById("YourSectionId").remove();
return true;
}
return true;

Date

Set a field to today's date + 7 

Let's say you want to automatically set a close date for an Opportunity to today's date plus 7 days. With the below code, you can do just that. If you need a different field than Close Date, change 'Opportunity.CloseDate' to the ID of the field you would like to use. For more information on how we built this code, check out this article from Mozilla Firefox. 

function FF_OnAfterRender() {

var date = new Date();

date.setDate(date.getDate() + 7);

 

var dateMsg = (date.getMonth()+1) +'/'+ date.getDate() +'/'+date.getFullYear();

document.getElementById("Opportunity.CloseDate").value = dateMsg;
}

Get today's date and set the time.

If you would like to set the date and time of a date/time field automatically, the below code can do just that. You'll just want to replace the field  #Contact\\.testdatetime__c' with the API name of the field you would like to use. 

function myFunction() {

    var d = new Date();

    d.setHours(02);

    d.setMinutes(0);

    d.setSeconds(0);

    d.setMilliseconds(0);

    var n = d.toISOString();

    $('#Contact\\.testdatetime__c').val(n);

}

 

function FF_OnAfterRender() {

myFunction()

} 

Prevent typing input into date fields

If you want to ensure your end users must select a date from the calendar picker.

function FF_OnAfterRender() {

    $('.hasDatepicker').keydown(function(e) {

   e.preventDefault();

})};

Change Datepicker to DD/MM/YY format 

Changes the date in the format used most often for our clients in Europe and Australia.

function FF_OnAfterRender(){

jQuery(".hasDatepicker").each(function(){

jQuery(this).datepicker("destroy");

jQuery(this).datepicker({

dateFormat: "dd/mm/yy"

});

});

return true;

}

function FF_OnBeforeSave(){

jQuery(".hasDatepicker").each(function(){

var vText = jQuery(this).val();

var vDates = vText.split('/');

console.log(vDates[0]);

console.log(vDates[1]);

console.log(vDates[2]);

jQuery(this).val(vDates[1] + "/" + vDates[0] + "/" + vDates[2]);

});

return true;

}  


Change Datepicker to DD/MM/YY format for Repeatable Sections

function FF_OnAfterRender(){

AddEvent();

jQuery(".hasDatepicker").each(function(){

jQuery(this).datepicker("destroy");

jQuery(this).datepicker({

  dateFormat: "dd/mm/yy"

});

});

return true;

}

function AddEvent(){

jQuery(".ff-alink.ff-add").click(function(){

jQuery(".hasDatepicker").each(function(){

jQuery(this).datepicker("destroy");

jQuery(this).datepicker({

  dateFormat: "dd/mm/yy" }); });

});

}

function FF_OnBeforeSave(){

jQuery(".hasDatepicker").each(function(){

var vText = jQuery(this).val();

var vDates = vText.split('/');

console.log(vDates[0]);

console.log(vDates[1]);

console.log(vDates[2]);

jQuery(this).val(vDates[1] + "/" + vDates[0] + "/" + vDates[2]);

});

return true;

}

 

Display alert when date entered is before a certain date

Show error when a date is entered prior to the allowable range.  This example will throw an error if the date entered is not greater than 7 days from today's date.

function FF_OnAfterRender(){
$("#YourObject\\.YourFieldId").focusout(function checkEventDate(){
var eventDate = new Date();

eventDate = document.getElementById("YourObject.YourFieldId").value;

var selectedEventTime = new Date(eventDate).getTime();

var timestamp = new Date().getTime() + (7 * 24 * 60 * 60 * 1000);

if (timestamp > selectedEventTime) {
alert("Your event date entered must be 6 days or more out.");
document.getElementById("YourObject.YourFieldId").value = '';
return false;
}
else if (timestamp < selectedEventTime) {
return true;
}
else {
return true;
}
});
}

 

Field Formatting and Validation

Simple phone number field formatting

This formatting will place your phone number fields with a (555)-555-5555 format.  This only applies to numbers as they are entered from an end-user.  A text label should be added to your form to direct users to enter only numbers on the form.

$('#Contact\\.HomePhone').on('change', function() {

        var number = $(this).val()

        number = number.replace(/(\d{3})(\d{3})(\d{4})/, "($1)$2-$3");

        $(this).val(number)

    });

Prevent Text input but allow numeric input

If you have a field type where you want to ensure your end users do not enter any characters except numbers.

$(document).ready(function() {

    $("[vatt=DOUBLE\\(6\\,0\\)]").keydown(function(event) {

        // Allow: backspace, delete, tab, escape, and enter

        if ( event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||

             // Allow: Ctrl+A

            (event.keyCode == 65 && event.ctrlKey === true) ||

             // Allow: home, end, left, right

            (event.keyCode >= 35 && event.keyCode <= 39)) {

                 // let it happen, don't do anything

                 return;

        }

        else {

            // Ensure that it is a number and stop the keypress

            if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105 )) {

                event.preventDefault();

            }  

        }

    });

});

Character Counter

If you want a particular field to display a character counter to ensure your users do not go over the limit. Replace  '#Contact\\.Description' with the field you'd like to have a character counter.

$(document).ready(function() {

    var text_max = 99;

    $('#textarea_feedback').html(text_max + ' characters remaining');

 

   $('#Contact\\.Description').keyup(function() {

        var text_length = $('#Contact\\.Description').val().length;

        var text_remaining = text_max - text_length;

 

       $('#textarea_feedback').html(text_remaining + ' characters remaining');

    });

});

Change #textarea_feedback to match your general text field's Field ID, or populate a general text field with <span id="textarea_feedback"></span>

Trim Whitespace from the beginning and end of a given field.

If you want to make sure your end users do not add any white space with a field. Change  'Contact.MobilePhone' and 'Contact.Email' to the fields you would like to modify.

trim()

function  FF_OnBeforeSave() { 

document.getElementById('Contact.MobilePhone').value = document.getElementById('Contact.MobilePhone').value.trim();

document.getElementById('Contact.Email').value = document.getElementById('Contact.Email').value.trim();

return true;

}

Alert user if minimum number of characters of characters is not met

// minimum number of characters
var num_chars = 5;

// add change event to field
fs('#Contact\\.your_field_ID').change(function(e) {
// anytime the value is changed in this field,
// if the length is less than the minimum allowed
// display alert message
if (fs(this).val().length < num_chars) {
alert("Please enter exactly 5 characters in this field");
}
});

Remove trailing zeroes for longitude and latitude fields

This code will remove trailing zeroes form any type of field but the sample use case is specifically targetted for longitude and latitude location fields.

function FF_OnAfterRender(){
var leadingZeroes = /[0]+$/;

var beforeLat = document.getElementById("YourObject.YourLatField").value;
var beforeLong = document.getElementById("YourObject.YourLongField").value;

var afterLat= beforeLat.replace(leadingZeroes,''); // Remove trailing 0's
var afterLong = beforeLong.replace(leadingZeroes,''); // Remove trailing 0's
document.getElementById("YourObject.YourLatField").value = afterLat;
document.getElementById("YourObject.YourLongField").value = afterLong;
return true;
}

Remove a section of a form if a value within the section is empty

This code will remove an entire section of your submitted form data prior to saving the results to Salesforce if a certain field within the section is empty.

function FF_OnBeforeSave(){
var yourField = document.getElementById("YourObject.YourField").value;
if(yourField === "") {
$('#YourObject\\.YourField').parents().eq(2).remove();
}
return true;
}

Use regular expressions for field validation.

In this example, enforce a minimum and maximum character count of 10 characters. If character count is not me, display alert and focus on field.

function FF_OnAfterRender() {
// set attributes for html field
fs('#Contact\\.MobilePhone').attr('pattern', '[0-9]{10}');
fs('#Contact\\.MobilePhone').attr('minlength', '10');
fs('#Contact\\.MobilePhone').attr('maxlength', '10');

//call function to validate field input
fs('#Contact\\.MobilePhone').change(function() {
validateField();
});
return true;
}

function validateField() {
var re = new RegExp("[0-9]{10}");
//display alert window and focus on field if input does not meet reg ex criteria
if (!re.test(fs('#Contact\\.MobilePhone').val())) {
alert('Please enter exactly 10 digits');
fs('#Contact\\.MobilePhone').focus();
}
}

Remove a hidden section on submit

If you are wanting to prevent child objects from writing any values on submission you can use this javascript to remove a hidden child object section when a user submits the form.

function FF_OnBeforeSave() {
var yourSectionId = document.getElementById("your_ffSection#").style.display == "none";

if (yourSectionId){
document.getElementById("ffSection16").remove();
}
return true;
}

Form Styling and Behavior

Disable Drag and Drop

Used to workaround a current defect with multiple file upload fields on the same page. Currently dragging and dropping a file to upload will cause the file to be uploaded to every upload field on the form.

$(".ff-forms").bind("drop", function(e){

            e.preventDefault();

            return false;

        });

Clear values of fields in repeatable sections 

By default, repeatable sections retain the information from the first object. With the code below, you can make it so each new record of the repeatable object has blank values.

function FF_OnAfterRender() {

BindClickHandlers();

}

function ClearNewRepeatableSection(elem) {

console.log("Clearing Repeatable Section");

/* clear out the values from text boxes of newly added section*/

$(elem).parents('.ff-sec-repeat-wrapper').next().find('input[type="textbox"]').val('');

$(elem).parents('.ff-sec-repeat-wrapper').next().find('textarea').val('');

// this line prevents picklists that are hidden from being cleared

$(elem).parents('.ff-sec-repeat-wrapper').next().find('select[data-ishidden="false"]').val('');

BindClickHandlers();

return true;

}

function BindClickHandlers(){

$('.ff-sec-repeat-wrapper a.ff-add').unbind('click');

$('.ff-sec-repeat-wrapper a.ff-add').bind('click', function () {

AddToRepeatableSection(this);

ClearNewRepeatableSection(this);

});

$('.ff-sec-repeat-wrapper a.ff-remove').unbind('click');

$('.ff-sec-repeat-wrapper a.ff-remove').bind('click', function () {

RemoveFromRepeatableSection(this);

BindClickHandlers();

});

}

Page redirect after submission

To redirect your users to a new page after submission. 

function  FF_OnAfterSave()

{

$("#dialog").dialog({

    close: function () {

        window.location = "http://www.google.com";

    }

});

}

Auto-Resize textarea fields for PDFs

Useful for clients who expect users will submit long blocks of text and need the information to be present on a PDF.

function FF_OnInitSave() {

$('textarea.ff-textarea,input.ff-input-type.ff-type-text').each(function(indx,elem){

var parentElem=$(elem).parent();

$(parentElem).find('.ff-pdf-div').remove();

var classNames=$(elem).attr('class');

classNames+=' ff-pdf-div';

$(elem).css('display','none');

$(parentElem).append(getPdfDivBlock($(elem).val(),classNames,$(elem).width()));

});

return true;

}

function FF_OnAfterSave(){

$('textarea.ff-textarea,input.ff-input-type.ff-type-text').each(function(indx,elem){

var parentElem=$(elem).parent();

$(parentElem).find('.ff-pdf-div').remove();

$(elem).css('display','');

});

}

function getPdfDivBlock(txt,classNames,width){

var pdfDiv=$('<div/>',{'class':classNames});

$(pdfDiv).css('width',width);

$(pdfDiv).css('word-break','break-word');

return $(pdfDiv).html(txt);

}

Show any hidden fields after a form has been submitted

Useful in cases where a client wants to show any hidden fields on a PDF.

function  FF_OnBeforeSave() { 

$('.ff-group-row').show();

  return true;

 }

Remove "Required" from footer label 

To remove the 'required' text from a required field.

function FF_OnAfterRender(){

$('.ff-footnote-label').html('')
$('.ff-required-mark').html('')

}

Dynamically generate form header image from hidden url field on a form

This code will allow you to reuse campaign or signup forms and have the header dynamically changes based on a hidden url field on a form.

function FF_OnAfterRender()
{
var imageUrl = fs('#OBJECTNAME\\.IMAGEURLFIELDNAME').val();
fs('.ff-header').css({'background-image': 'url(' + imageUrl + ')', 'height':'375px', 'width':'auto', 'max-width':'1000px' , 'background-repeat':'no-repeat'});
}

Redirect to different webpage upon form submission based on field selection.

function FF_OnAfterSave() {
if (fs('#Contact\\.LeadSource').val() === "Web") {
window.location = "https://sfapphelp.formstack.com/hc/en-us";
} else {
window.location = "https://www.formstack.com/";
}

return true;

}

Uncheck a radio button by clicking on it.

function FF_OnAfterRender() {
//Bind to all elements that have the ff-ext-radio-css class
fs('.ff-ext-radio-css').each(function() {
fs(this).bind("click", function() {
//Only perform this action is the radio button has already been selected
if (fs(this).attr('class') == "ff-ext-radio-css ff-ext-selected") {
//Remove that ff-ext-selected CSS Class
fs(this).removeClass("ff-ext-selected");
// Clear the value of the selected item from the picklist
fs(this).parent().parent().parent().next().val("");
// Stop any additional events from being triggered on this action
event.stopImmediatePropagation();
}
});
});
}
 

Add Header Text and Change Font

Add text above the form and import a font.

$(document).ready(function() {

// Append this font stylesheet in the head
$("head").append("<link rel='stylesheet' id='google-fonts-css' href='https://fonts.googleapis.com/css?family=Lato%7CArimo%7CMontserrat&#038;ver=5.3.2' type='text/css' media='all' />");

// Appends some HTML after the .ff-header
$(".ff-header").append("<div class='header_text'><span>Welcome to </span><br>The Cirrus Life</div>");

});

Line Break after Field Label

Insert a line break after each Field Label.

//Find the ID like in the example below or class and use . instead

$("#lblRebateApplication__cApplicant_Name__c:contains(':')").html(function () {
return $(this).html().replace(": ", ": <br />");
});

National Insurance Number and Postal Code Validation

function FF_OnAfterRender() {
// set attributes for html field
fs('#sked_Referral__c\\.National_Insurance_Number__c').attr('pattern', '[a-zA-Z]{2}[0-9]{6}[a-zA-Z]');
fs('#sked_Referral__c\\.sked_Referee_Post_Code__c').attr('pattern', '[a-zA-Z]{1,2}[0-9][0-9a-zA-Z]\s[0-9][a-zA-Z]{2}');

//call function to validate field input
fs('#sked_Referral__c\\.National_Insurance_Number__c').change(function() {
validateNationalInsuranceNumber();
});
fs('#sked_Referral__c\\.sked_Referee_Post_Code__c').change(function() {
validatePostCode();
});
return true;
}

function validateNationalInsuranceNumber() {
var re = new RegExp("[a-zA-Z]{2}[0-9]{6}[a-zA-Z]");
//display alert window and focus on field if input does not meet reg ex criteria
if (!re.test(fs('#sked_Referral__c\\.National_Insurance_Number__c').val())) {
//alert('Please enter your post code in one of the correct formats');
alert("Please enter your National Insurance Number in the correct format below:" + "\n" + "\n" + "AB123456A");
fs('#sked_Referral__c\\.National_Insurance_Number__c').focus();
}
}

function validatePostCode() {
var re = new RegExp("[a-zA-Z]{1,2}[0-9][0-9a-zA-Z]\s[0-9][a-zA-Z]{2}");
//display alert window and focus on field if input does not meet reg ex criteria
if (!re.test(fs('#sked_Referral__c\\.sked_Referee_Post_Code__c').val())) {
//alert('Please enter your post code in one of the correct formats');
alert("Please enter your post code in one of the correct formats below:" + "\n" + "\n" + "AA9A 9AA" + "\n" + "A9A 9AA" + "\n" + "A9 9AA" + "\n" + "A99 9AA" + "\n" + "AA9 9AA" + "\n" + "AA99 9AA");
fs('#sked_Referral__c\\.sked_Referee_Post_Code__c').focus();
}
}

Display two field input boxes side by side for repeatable sections and custom CSS

//find all classes with name "ff-row"
//if condition, then apply css.

/*
{
color:"red",
backgroundColor:"blue"
}
*/

function applyCss(cssIn = {}){
var rows = document.getElementsByClassName('ff-item-row');
var cssIds = ['FirstName','LastName','Email','Phone']
for(var i of rows){
var inputs = i.getElementsByTagName('input');
var foundInput = false;
if(inputs.length){
for(var j of inputs){
for(var id of cssIds){
if(j.id.indexOf('Account.Contact') > -1&&j.id.indexOf(id) > -1){
foundInput = true;
break;
}
if(foundInput) break;
}
if(foundInput){
//Style the css
for(var key in cssIn){
i.style[key] = cssIn[key];
}
}
}
}
}
}

var targetCss = {
width:"47.9%",
display:"inline-block"
}

function FF_OnAfterRender(){
applyCss(targetCss);
}

for(var i of document.getElementsByClassName("ff-alink ff-add")){
i.addEventListener('click',function(){
applyCss(targetCss);
});
}

Customize Draft Discard Messages

Update the two variables at the top of this recipe to change the messages displayed when user discards a saved draft and when a user returns to a discarded draft.

//Message displayed when a user clicks the "Discard" button
var DISCARD_DRAFT_MESSAGE = "";
//Message displayed when a user returns to a discarded draft
var INVALID_DRAFT_MESSAGE = "";

function FF_OnAfterRender() {
    if(INVALID_DRAFT_MESSAGE !== ""){
        window.ffPrompt_InvalidSavedForm = INVALID_DRAFT_MESSAGE;
    }

    if(DISCARD_DRAFT_MESSAGE !== ""){
        var discardButton = fs('#btndiscard');
        if(discardButton.length > 0){
            discardButton.on('click', function() {
                var discardDialog = document.getElementById('dialog');
                discardDialog.innerHTML = DISCARD_DRAFT_MESSAGE;
            });
        }
    }

}


Pre-populating Fields

Write users IP to a field on your form

function FF_OnAfterRender(){
$.getJSON("https://api.ipify.org/?format=json", function(e) {
document.getElementById("Contact.Description").value = e.ip;
});
} 

 

Parse value from URL and populate form field with value.

function FF_OnAfterRender() {
parseURL();
return true;
}

 

function parseURL() {

// Create variable to Store the parsed URL
var parsed_url;
// Store the URL into variable
var url = window.location.href;
//remove front part of url
url = url.split('/')[5];
//get value from url
parsed_url = url.split('-')[0];

fs('#Contact\\.AccountId\\.Site').val(parsed_url);

}

Populate field with lookup text.

While rules can be used to populate a field with the value from a lookup field, the lookup field submits the record id of the record selected from the list view. This is preferable, however, in the instance that you need to populate a field with the name of the selected record instead of the record id, the following recipe can be used.

function FF_OnBeforeSave() {

if (fs('#inputContact\\.Case\\.A\\.AccountId').val() !== 'Other') {
fs('#Contact\\.LastName').val(fs('#inputContact\\.Case\\.A\\.AccountId').val());
}

return true;
}

 

Was this article helpful?
7 out of 10 found this helpful

Comments

0 comments

Article is closed for comments.