Skip to content
Scroll To TopjQuery(function($){
var lastPct = null;
var progressData = {}; // Store progress per form
function getFormId($container) {
return $container.closest('.nf-form-cont').find('form').attr('id') || 'default';
}
function injectSmooth(){
$('.nf-mp-header .nf-progress-container').each(function(){
var $c = $(this),
formId = getFormId($c),
$n = $c.find('.nf-progress'),
m = ($n.attr('style')||'').match(/width:\s*([\d.]+)%/),
pct = m ? parseFloat(m[1]) : 0,
$s = $c.find('.smooth-bar');
// Initialize form progress tracking
if (!progressData[formId]) {
progressData[formId] = { lastPct: pct, isAnimating: false };
}
// Check if smooth-bar exists and is properly attached
if (!$s.length || $s.parent()[0] !== $c[0]) {
// Remove any orphaned smooth-bars
$c.find('.smooth-bar').remove();
// Create new smooth-bar with last known position
var initWidth = progressData[formId].lastPct + '%';
$s = $('')
.css({
'width': initWidth,
'position': 'absolute',
'top': 0,
'left': 0,
'height': '100%',
'background': '#your-color', // Add your styling
'transition': 'none', // We'll handle animation with jQuery
'z-index': 1
})
.prependTo($c);
console.log('🔄 Recreated smooth-bar at', initWidth, 'for form', formId);
}
// Update progress if changed and not currently animating
if (pct !== progressData[formId].lastPct && !progressData[formId].isAnimating) {
progressData[formId].isAnimating = true;
$s.stop(true, false).animate({
width: pct + '%'
}, {
duration: 500,
easing: 'swing',
complete: function() {
progressData[formId].lastPct = pct;
progressData[formId].isAnimating = false;
}
});
console.log('🎬 Animating progress from', progressData[formId].lastPct + '%', 'to', pct + '%');
}
});
}
// Ninja Forms specific events (most reliable)
$(document).on('nfFormReady', function(e, layoutData) {
console.log('📋 NF Form Ready');
setTimeout(injectSmooth, 50); // Small delay for DOM settling
});
$(document).on('nfFormSubmitResponse', function(e, response) {
if (response.data && response.data.mp_nav) {
console.log('📋 NF Multi-part navigation');
setTimeout(injectSmooth, 100);
}
});
// Navigation events
$(document).on('click', '.nf-next, .nf-previous, .nf-breadcrumb', function() {
setTimeout(injectSmooth, 150); // Longer delay for navigation
});
// Field change monitoring with debouncing
var fieldChangeTimeout;
$(document).on('change', '.nf-form-cont input, .nf-form-cont select, .nf-form-cont textarea', function() {
clearTimeout(fieldChangeTimeout);
fieldChangeTimeout = setTimeout(function() {
injectSmooth();
}, 100); // Debounce rapid changes
});
// Robust MutationObserver for DOM changes
if (window.MutationObserver) {
var observer = new MutationObserver(function(mutations) {
var needsReinject = false;
mutations.forEach(function(mutation) {
// Check if progress container structure changed
if (mutation.type === 'childList') {
$(mutation.target).closest('.nf-progress-container').each(function() {
needsReinject = true;
});
// Check if smooth-bar was removed
$(mutation.removedNodes).each(function() {
if ($(this).hasClass('smooth-bar')) {
needsReinject = true;
}
});
}
// Check for style changes to progress bar
if (mutation.type === 'attributes' &&
mutation.attributeName === 'style' &&
$(mutation.target).hasClass('nf-progress')) {
needsReinject = true;
}
});
if (needsReinject) {
setTimeout(injectSmooth, 50);
}
});
// Observe the entire form container
$('.nf-form-cont').each(function() {
observer.observe(this, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style']
});
});
}
// Fallback polling (reduced frequency)
setInterval(injectSmooth, 500);
// Initial injection
$(document).ready(function() {
setTimeout(injectSmooth, 100);
});
});