-
Notifications
You must be signed in to change notification settings - Fork 17
Custom JS for fields
Here I will try to give a universal example of how to write custom JS code for form fields. For example, I will take the code from one ish and rework it in a new way. After that we will see what is their difference.
The task of the code is to limit the number of checkboxes to be selected.
(The author @Lonsdale201)
jQuery( document ).ready( function ( $ ) {
var maxChecked = 2; /* Modfily the maximum checked elements */
var checkedCount = 0;
var warningTextAdded = false;
$( '.my_input_checkbox' ).click( function () {
if ( checkedCount >= maxChecked && $( this ).prop( 'checked' ) ) {
$( this ).prop( 'checked', false );
}
else {
if ( !$( this ).prop( 'checked' ) ) {
checkedCount--;
}
else {
checkedCount++;
}
}
if ( checkedCount < maxChecked ) {
$( '#warning-text2' ).remove();
warningTextAdded = false;
}
else if ( !warningTextAdded ) {
var warningText = $(
'<div id="warning-text2">You cant select more</div>' );
$( '.my_input_checkbox' ).
last().
closest( '.jet-form-builder__field-wrap' ).
append( warningText );
warningTextAdded = true;
}
} );
} );
const {
addFilter,
addAction,
} = JetPlugins.hooks;
const findClassName = item => item.includes( 'check-limit' );
const limitCount = 2;
addAction(
'jet.fb.input.makeReactive',
'jet-form-builder/checkbox-limit-restriction',
/**
* @param input {InputData}
*/
function ( input ) {
// get first checkbox node
const [ nodeMain ] = input.nodes;
if ( 'checkbox' !== nodeMain.type ||
![ ...nodeMain.classList ].some( findClassName )
) {
return;
}
const wrapper = nodeMain.closest( '.jet-form-builder-row' );
const messageNode = document.createElement( 'div' );
messageNode.classList.add( 'warning-text' );
messageNode.innerText = 'You cant select more';
// triggered at each change of the value
input.watch( () => {
const { length: count } = input.value.current;
const isFull = count >= limitCount;
for ( const node of input.nodes ) {
if ( node.checked ) {
continue;
}
node.disabled = isFull;
}
if ( isFull ) {
wrapper.append( messageNode );
}
else {
messageNode.remove();
}
} );
},
);
If you use JetFormBuilder <=2.1.11
version, so you have no choice. You need to write only in old-style format.
If the plugin version is >=3.0.0
, then you can write as you wish. However, I recommend writing in the new format and here is why.
One of the key points is jQuery.ready
. This event is executed only once, when the page is loaded. But our forms may have a Repeater Field in them, or be rendered using JetPopup using the ajax method and in these cases only the internal JetFormBuilder hooks should be used.
Of course, if you want, you can continue to write in the old style, but it will be much more difficult.
To prove this, let's try to write a compatibility of our old code for the repeater.
First, let's move our checkbox field inside the repeater in the form editor. At this step, we can see that our code does not work at all, because we add a "handler" to click on the checkboxes that are currently present on the page.
At first glance, it seems that jQuery.on should help, but it does not. Let's see why. Replace
$( '.my_input_checkbox' ).click( function () { /* code */ } );
with
jQuery( document ).on( 'click', '.my_input_checkbox', function () { /* Move the code without changes */ } );
And here is a bottleneck because of the local variable checkedCount
. We have only one variable for the whole script and when adding a new repeater item, we will no longer be able to select checkboxes.
And here is a bottleneck because of the local variable checkedCount
. We have only one variable for the whole script and when adding a new repeater item, we will no longer be able to select checkboxes.
This problem can be bypassed as follows:
jQuery( document ).ready( function ( $ ) {
var maxChecked = 2; /* Modfily the maximum checked elements */
var warningTextAdded = false;
jQuery( document ).on( 'click', '.my_input_checkbox', function () {
const wrapper = $( this ).closest( '.jet-form-builder__fields-group' );
// field-relative counter
let checkedCount = wrapper.data( 'limit-count' );
if ( undefined === checkedCount ) {
wrapper.data( 'limit-count', 0 );
checkedCount = 0;
}
if ( checkedCount >= maxChecked && $( this ).prop( 'checked' ) ) {
$( this ).prop( 'checked', false );
}
else {
if ( !$( this ).prop( 'checked' ) ) {
wrapper.data( 'limit-count', --checkedCount );
}
else {
wrapper.data( 'limit-count', ++checkedCount );
}
}
if ( checkedCount < maxChecked ) {
$( '#warning-text2' ).remove();
warningTextAdded = false;
}
else if ( !warningTextAdded ) {
var warningText = $(
'<div id="warning-text2">You cant select more</div>' );
$( '.my_input_checkbox' ).
last().
closest( '.jet-form-builder__field-wrap' ).
append( warningText );
warningTextAdded = true;
}
} );
} );
We have changed how the counters are stored for each field. Now this example is compatible with the repeater field. But we spent extra time on this. And we will have to spend it again when we want this script to work in popups (JetPopup, Elementor Pro).
<?php
// functions.php of your child theme or own plugin
const CHECKBOX_LIMIT_HANDLE = 'jet-fb-custom-checkbox-limit';
add_action(
'jet-form-builder/before-start-form-row',
function ( \Jet_Form_Builder\Blocks\Types\Base $block ) {
if ( 'checkbox-field' !== $block->get_name() ) {
return;
}
wp_enqueue_script( CHECKBOX_LIMIT_HANDLE );
}
);
add_action(
'wp_enqueue_scripts',
function () {
wp_register_script(
CHECKBOX_LIMIT_HANDLE,
'path/to/your/script.js',
// for >= 3.0.0 JetFormBuilder
array( 'jet-plugins' ),
// for <= 2.1.11 JetFormBuilder
// array()
'1.0.0',
true
);
}
);
Need more information? Check out the official documentation at jetformbuilder.com or contact Crocoblock Support