Skip to content

Instantly share code, notes, and snippets.

@Qubadi
Last active March 21, 2025 16:46
Show Gist options
  • Save Qubadi/c83878e6244261b39ff387d4c9739f67 to your computer and use it in GitHub Desktop.
Save Qubadi/c83878e6244261b39ff387d4c9739f67 to your computer and use it in GitHub Desktop.
JetFormBuilder media field, enhanced choose file
UPDATED: 01.02.2025
1. We've enhanced the JetFormBuilder with a refined custom code, improving both style and functionality for file selection. The latest
update introduces support for the repeater field's media capabilities, offering a more streamlined and efficient user experience for
handling multiple files within forms.
2. Copy this code, create a new HTML snippet, and paste it into your snippet plugin. Save it as a header or footer.
__________________________________________
See the youtube tutorials here ( OLD ):
https://youtu.be/lOghzLiR73Q?si=DbNNcCkKzkv_mAQl
__________________________________________
<style>
/* Custom styles for the file upload field */
.jet-form-builder__field-wrap.jet-form-builder-file-upload {
background: #ecf6ff !important;
border: 3px dashed #c7d4e1 !important;
padding: 20px !important;
text-align: center;
position: relative;
margin-bottom: 20px;
display: flex;
flex-direction: column;
align-items: center;
border-radius: 6px !important;
}
/* Styles for the image upload */
.jet-form-builder-file-upload__file img {
display: block;
width: 100%;
height: 100% !important;
padding: 0;
margin: 0;
-o-object-fit: cover;
object-fit: cover;
-o-object-position: center center;
object-position: center center;
border-radius: 6px !important;
box-shadow: 0 0 30px -8px rgba(0, 0, 0, 0.24) !important;
}
/* Styles for image content */
.jet-form-builder-file-upload__content {
min-height: auto !important;
}
/* Styles for the custom "Choose File" and "File Uploaded" buttons */
.addfile {
padding: 10px 20px;
background-color: #0037fd !important;
color: #ffffff !important;
border: none !important;
font-size: 16px;
font-weight: 600;
cursor: pointer;
border-radius: 6px;
margin-top: 10px; /* Space between button and label */
transition: opacity 0.3s ease, transform 0.3s ease; /* Smooth transition */
}
.addfile:hover {
background-color: #000000 !important;
color: #ffffff !important;
}
/* Styles for the label that shows file upload status */
.labeladdfile {
padding: 6px 12px;
background-color: transparent;
color: #000000 !important;
font-size: 12px;
font-weight: 400;
display: block;
margin-top: 10px;
border-radius: 6px;
transition: opacity 0.3s ease, transform 0.3s ease; /* Smooth transition */
}
/* Class added when files are uploaded */
.files-uploaded {
background-color: #09b872 !important;
padding: 6px 12px;
color: #ffffff !important;
border-radius: 6px;
}
/* Hide the default file input visually */
.jet-form-builder-file-upload__input {
display: none;
}
/* Responsive adjustments */
@media (max-width: 767px) {
.addfile, .labeladdfile {
padding: 8px 16px;
font-size: 12px;
}
}
@media (max-width: 1024px) {
.addfile, .labeladdfile {
padding: 8px 16px;
font-size: 12px;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
const { addAction } = window.JetPlugins.hooks;
addAction('jet.fb.input.makeReactive', 'set-upload-labels', function(input) {
if (!input?.nodes?.length || !input.nodes[0].classList.contains('jet-form-builder-file-upload__input')) {
return;
}
const $ = jQuery;
const upload = $(input.nodes[0]);
const fields = $(input.nodes[0].closest('.jet-form-builder-file-upload__fields'));
if (!fields.find('.addfile').length) {
fields.append(`<input type="button" class="addfile" value="Choose File"/>`);
fields.append(`<div class="labeladdfile">Choose File</div>`);
}
const labelAdd = fields.find('.labeladdfile');
const buttonAdd = fields.find('.addfile');
upload.css('display', 'none');
buttonAdd.click(function() {
upload.trigger('click');
});
function updateFileLabel() {
const fileCount = upload[0].files.length;
if (fileCount > 0) {
buttonAdd.val('File Uploaded');
labelAdd.html(`Uploaded files (${fileCount})`);
labelAdd.addClass('files-uploaded');
buttonAdd.css({ opacity: 1, transform: 'scale(1)' }); // Ensure button is visible
labelAdd.css({ opacity: 1, transform: 'scale(1)' }); // Ensure label is visible
} else {
resetFileLabel();
}
}
function resetFileLabel() {
// Smoothly hide the button and label
buttonAdd.css({ opacity: 0, transform: 'scale(0.9)' });
labelAdd.css({ opacity: 0, transform: 'scale(0.9)' });
// After the transition, reset the text and show the button/label smoothly
setTimeout(() => {
buttonAdd.val('Choose File');
labelAdd.html('Choose File');
labelAdd.removeClass('files-uploaded');
buttonAdd.css({ opacity: 1, transform: 'scale(1)' });
labelAdd.css({ opacity: 1, transform: 'scale(1)' });
$('.jet-form-builder-file-upload__file').remove(); // Remove uploaded image preview
}, 300); // Match the transition duration
}
upload.on('change', updateFileLabel);
// Detect when the remove button is clicked
$(document).on('click', '.jet-form-builder-file-upload__file-remove', function() {
setTimeout(() => {
if ($('.jet-form-builder-file-upload__file').length === 0) {
resetFileLabel();
}
/*
* If there are still files left after removing, update the count in real time.
*/
if ($('.jet-form-builder-file-upload__file').length > 0) {
buttonAdd.val('File Uploaded');
labelAdd.html(`Uploaded files (${$('.jet-form-builder-file-upload__file').length})`);
labelAdd.addClass('files-uploaded');
buttonAdd.css({ opacity: 1, transform: 'scale(1)' });
labelAdd.css({ opacity: 1, transform: 'scale(1)' });
}
}, 100);
});
// Detect when the form is successfully submitted
const successMessageObserver = new MutationObserver((mutationsList) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
const successMessage = $(mutation.addedNodes).find('.jet-form-builder-message--success');
if (successMessage.length > 0) {
resetFileLabel(); // Reset the button and label smoothly
}
}
}
});
// Observe the form container for success messages
const formContainer = $('.jet-form-builder')[0];
if (formContainer) {
successMessageObserver.observe(formContainer, { childList: true, subtree: true });
}
function resetFileInput() {
upload.val('');
resetFileLabel(); // Use the same reset function for consistency
input.value.set([]);
}
/*
* == CODE FROM YOUR SECOND SNIPPET (POPUP + MAX-FILE CHECK) ==
*/
function validateFiles(files) {
const maxFileSize = 2 * 1024 * 1024; // 2 MB
const maxFileCount = 2; // Max 2 files
let valid = true;
if (files.length > maxFileCount) {
valid = false;
} else {
Array.from(files).forEach(file => {
if (file.size > maxFileSize) {
valid = false;
}
});
}
return valid;
}
// Updated to wait a moment after clicking "OK" before reloading
function showErrorMessage() {
const errorMessage = $('.jet-form-builder-row.field-has-error .error-message').text().trim();
if (errorMessage) {
alert(errorMessage);
resetFileInput();
// Delay the page reload so user sees "Choose File" again
setTimeout(() => {
window.location.reload();
}, 700);
}
}
// On file input change, if invalid, show popup & reset
upload.on('change', function() {
const files = upload[0].files;
if (!validateFiles(files)) {
showErrorMessage();
}
});
});
});
</script>
@Qubadi
Copy link
Author

Qubadi commented Mar 21, 2025

Awesome script!!! Thank u so much!

U welcome🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment