Examples for solving requirements with the Frontend Web Assets
Note: These features are part of the Visforms Subscription and are not included in the free Visforms version.
Calculate and display sum of many fields
Subjects
The following topics are included in the example:
- Respond to user changes.
- Determine the numerical values of number fields and text fields of the form.
- Combine fields by assigning a common “CSS class of the field” in the field configuration.
- Treat input fields as a group using a common CSS class.
- Address output field using a CSS class.
- Output to a number field of the form.
- Run code after the form has been completely initialized.
Description
The form can contain a lot of number fields. You want to calculate and display a total for some of the number fields or for all number fields. The form reacts to every change made by the user and recalculates the total each time.
The fields are each addressed via their custom CSS classes. This CSS class is set in the field configuration, “Advanced” tab, “CSS class of field” option. In this case, the other two options for “CSS Class Control Group” and “CSS Class for Label” remain blank.
The 6 total fields
Each field that is to be included in the total must have the same CSS class set in the field configuration.
The total fields are addressed in the JavaScript code via the CSS class css-number-add.
The result field
The result field that receives and displays the current total must also have a field-specific custom CSS class set.
It is addressed in the JavaScript code via the CSS class css-number-add-result.
The JavaScript code
// calculate sum of field group labeled by common CSS-class 'css-number-add'
jQuery(document).ready(function() {
// console.log('FEWA script loaded');
jQuery('.css-number-add').bind('change keyup mouseup mousewheel', function() {
// re-calculate on value change
calculateSum();
});
jQuery('.visform').bind('visformsInitialised', function() {
// re-calculate on form is initialized
calculateSum();
});
});
function calculateSum() {
let sum = 0;
jQuery('.css-number-add').each(function() {
let val = jQuery(this).val();
// skip all of: is not a number
if(isNaN(val)) return true;
// keep multiplication with 1, otherwise it would be a simple string concatenation
sum += 1 * val;
});
jQuery('.css-number-add-result').val(sum);
}
Calculate and display the ISO calendar week for a date
Subjects
The following topics are included in the example:
- Respond to user changes.
- Read in a date and break it down into its components.
- React to the selected date format from the field configuration.
- Calculate the calendar week according to ISO-8601 (week starts on Monday).
- Set the value of a number field.
Description
The form field “birth date” is the date field for selecting a date.
The “ISO Calendar Week” form field automatically displays the calendar week of the currently selected date according to ISO-8601 (week starts on Monday).
Customization to your form
The following needs to be adapted to your form in the JavaScript code:
- The Visforms field ID for the date field: const dateFieldID = ‘479’;
- The Visforms field ID for the week field: const numberFieldID = ‘555’;
You can use text or number (as in the example) as the field type for the week field.
The JavaScript code
jQuery(document).ready(function() {
// console.log(' FEWA script loaded');
const dateFieldID = '479'; // Visforms date field ID of field list
const numberFieldID = '555'; // Visforms number field ID of field list
jQuery(`#field${dateFieldID}`).on('change', function() {
let value = jQuery(this).val();
let parts =value.split('.');
const date = new Date(`${parts[2]}-${parts[1]}-${parts[0]}`);
jQuery(`#field${numberFieldID}`).val(getWeekISO8601(date));
});
function getWeekISO8601(dt) {
const tdt = new Date(dt.valueOf());
const dayn = (dt.getDay() + 6) % 7;
tdt.setDate(tdt.getDate() - dayn + 3);
const firstThursday = tdt.valueOf();
tdt.setMonth(0, 1);
if (tdt.getDay() !== 4) {
tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7);
}
return 1 + Math.ceil((firstThursday - tdt) / 604800000);
}
});
Set up a spambot honeypot
Subjects
The following topics are included in the example:
- Hide a form field (type “email”) and not show it.
- Check whether a spambot has set a value in the hidden form field.
- Respond to form submission.
- Set a custom event handler for form submission.
- Prevent form submission.
- Show a message to the user.
Description
Visforms supports several effective ways to secure the form against spambots. If additional measures need to be taken, there are several simple methods. Here we show how a spambot honeypot can be set up with little effort.
A honeypot can be set up by adding another field of type “Email” that:
- is not visible to the user,
- but spambots fill the invisible field nicely.
Before submitting the form, it is checked whether the field is empty. If the invisible field of type “Email” is filled, the form will not be sent. Instead of submitting the form, a modal dialog with a quite misleading message is shown.
In principle it also works with a field of type “Hidden”. A hidden field is automatically not visible on the form. In this case, the one JavaScript line that hides the field would be unnecessary:
jQuery('div.field' + fieldID).css('display', 'none');
However, an invisible field of type ‘email’ is more suitable for spammers.
Customization to your form
The following adjustments are necessary to the JavaScript code and your form:
- In the form, add an additional field of type “Email” that is not required.
- Paste the JavaScript code in the form configuration, tab “Frontend Webassets”, tab “Form” into the “JavaScript” field.
- In the JavaScript code, change the value of the “formID” variable to the ID of your form.
- In the JavaScript code, change the value of the “fieldID” variable to the ID of your field.
The test code
The JavaScript code contains a test code at the end. The test code plays “spammer” and after waiting 4 seconds fills the invisible email field with an email address.
Note: On the productive side, this test code must be commented out or removed entirely.
The JavaScript code
// suppress form submit in case of spambot filled hidden field
jQuery(document).ready(function() {
// console.log('FEWA script loaded');
const formID = '44';
const fieldID = '464';
jQuery('div.field' + fieldID).css('display', 'none');
window['visform' + formID + 'SubmitAction'] = function (form) {
if('' !== jQuery('#field' + fieldID).val()) {
alert("Please log in first!");
return false;
}
return true;
};
// only for testing purposes: emulate spambot attack
window.setTimeout(function () {
jQuery('#field' + fieldID).val('spambot@text.de');
}, 4000);
});
Record a time period with date fields and time fields
Subjects
The following topics are included in the example:
- Respond to user changes.
- Determine the selected values of date fields.
- Determine the individually configured date format of the date fields.
- Determine the values of text fields of the form.
- Check for completeness of user information
- Programming and calculating with date values.
- Programming and calculating with time values.
- Parse a date in text format into a JavaScript “Date” object.
- Output to a text field of the form.
Description
The form has a date field and a text field for entering the time you fell asleep and the time you woke up. When the last field is filled, the calculation of the bedtime begins. The time difference in hours is displayed in another field.
Note: The calculation takes into account the possible different field settings for the date format. Different date formats can be set for date fields in the field configuration.
The JavaScript code
jQuery(document).ready(function() {
// console.log('FEWA script loaded');
const startDateID = '556'; // Visforms start date field ID of field list
const startTimeID = '557'; // Visforms start time (text) field ID of field list
const endDateID = '558'; // Visforms end date field ID of field list
const endTimeID = '559'; // Visforms end time (text) field ID of field list
const sleepingTimeID = '560'; // Visforms start time (text) field ID of field list
function calculateHours() {
// Get values from input fields
const startDateValue = jQuery(`#field${startDateID}`).val();
const startTimeValue = jQuery(`#field${startTimeID}`).val();
const endDateValue = jQuery(`#field${endDateID}`).val();
const endTimeValue = jQuery(`#field${endTimeID}`).val();
const startDateFormat = jQuery(`#field${startDateID}_btn`).attr('data-date-format');
const endDateFormat = jQuery(`#field${endDateID}_btn`).attr('data-date-format');
if(startDateValue === '' || startTimeValue === '' || endDateValue === '' || endTimeValue === '' ) {
return;
}
// Create date objects
const startDate = addTimeToDate(stringToDate(startDateValue, startDateFormat), startTimeValue);
const endDate = addTimeToDate(stringToDate(endDateValue, endDateFormat), endTimeValue);
// Calculate time difference in milliseconds
const timeDifference = endDate - startDate;
// Convert milliseconds to hours
let hoursDifference = timeDifference / (1000 * 60 * 60);
// Round to 2 digits
hoursDifference = Math.round((hoursDifference + Number.EPSILON) * 100) / 100
// Display the result
jQuery(`#field${sleepingTimeID}`).val(hoursDifference);
}
// Call the function when any of the relevant fields change
jQuery(`#field${startDateID}, #field${startTimeID}, #field${endDateID}, #field${endTimeID}`).on('change', calculateHours);
// You can also call the function initially if needed
// calculateHours();
});
function stringToDate(date, format) {
// parsing a string into a date
const delimiter = format.charAt(2);
const formatLowerCase = format.toLowerCase();
const formatItems = formatLowerCase.split(delimiter);
const dateItems = date.split(delimiter);
const monthIndex = formatItems.indexOf("%m");
const dayIndex = formatItems.indexOf("%d");
const yearIndex = formatItems.indexOf("%y");
const month = parseInt(dateItems[monthIndex]) - 1;
return new Date(dateItems[yearIndex], month, dateItems[dayIndex]);
}
function addTimeToDate(date, time) {
// replace all spaces
time = time.replace(/\s/g, '');
// split hours and minutes
const parts = time.split(':');
if(parts[0] === '') {
// empty time string
return date;
}
else if(parts.length == 1) {
// only hour present
date.setHours(parseInt(parts[0]));
return date;
}
else {
// hour and minutes present
date.setHours(parseInt(parts[0]), parseInt(parts[1]));
return date;
}
}