Enhancing User Interaction with a Custom jQuery Calculator

[ ][ ] July 31, 2024

Whats the Problem?

In web development, enhancing user interaction and ensuring data validation are crucial for providing a seamless experience. Our goal was to create an interactive calculator that dynamically updates results based on user input while providing immediate feedback for invalid entries. However, during implementation, we faced issues such as:

  • Validating numeric input in real-time.
  • Dynamically updating multiple fields based on calculations.
  • Handling invalid form submissions gracefully.
  • Ensuring compatibility with a Gravity Forms hidden field to store data.

The Solution


We developed a jQuery-based solution to address these challenges effectively.

<script>
var input = $('#nh-calculator__visits');
var gross = $('#gross');
var referrals = $('#referrals');
var hoursSaved = $('#hours-saved');
var yearOne = $('#year-one');
var yearTwo = $('#year-two');
var yearThree = $('#year-three');
var button = $('.nh-calculator__button');
var close = $('.nh-calculator__modal-close');
var modal = $('.nh-calculator__modal-wrapper');
```

**2. Linking with Gravity Forms:**
We ensured our script works seamlessly with Gravity Forms:
```javascript
var form = $('.gform_wrapper');
var id = form.length > 0 ? form.attr('id') : null;
var hidden = id ? $('#input_' + id.split('').pop() + '_6') : null;
```

**3. Input Validation with Debounce:**
To prevent performance issues, we used a debounce function to validate input in real-time:
```javascript
function debounce(func, wait, immediate) {
    var timeout;
    return function () {
        var context = this, args = arguments;
        var later = function () {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
}
```

**4. Validating Input:**
We ensured only numeric values are accepted and provided instant feedback for invalid entries:
```javascript
var validate = debounce(function (e) {
    var element = $(e.target);
    var text = element.val();
    var error = $('<span />', {
        class: 'nh-calculator__error',
        html: 'Please enter a number'
    });

    if (!e.target.validity.valid) {
        element.addClass('nhc-border-red');
        if (!element.next('.nh-calculator__error').length) {
            error.appendTo(element.parent());
        }
        if (hidden) hidden.val('');
    } else {
        element.removeClass('nhc-border-red');
        $('.nh-calculator').find('.nh-calculator__error').remove();
        if (hidden) hidden.val(text);
        woundCalculate();
    }
}, 250);
```

**5. Calculation Function:**
We performed calculations based on user input and updated the results dynamically:
```javascript
function stripComma(value) {
    return value.replace(/,/g, '');
}

function woundCalculate() {
    var visits = stripComma(input.val());
    if (isNaN(visits) || visits === "") {
        visits = 0;
    }
    var grossTotal = Math.floor((visits * 165 * 0.1) - (visits * 165 * 0.07));
    var referralsTotal = Math.floor(visits / 3 * 0.01 * 165 * 16);
    var hoursTotal = Math.floor(visits * 5 / 60 * 0.75 * 165);
    var yearOneTotal = grossTotal * 12;
    var yearTwoTotal = grossTotal * 24;
    var yearThreeTotal = grossTotal * 36;

    gross.html('+ $' + grossTotal.toLocaleString('en-US'));
    referrals.html('+ $' + referralsTotal.toLocaleString('en-US'));
    hoursSaved.html('+ $' + hoursTotal.toLocaleString('en-US'));
    yearOne.html('+ $' + yearOneTotal.toLocaleString('en-US'));
    yearTwo.html('+ $' + yearTwoTotal.toLocaleString('en-US'));
    yearThree.html('+ $' + yearThreeTotal.toLocaleString('en-US'));
    console.log(visits);
}
```

**6. Event Handlers:**
We set up event handlers for user interactions:
```javascript
input.on('keyup', validate);
input.on('blur', validate);

button.on('click', function (e) {
    e.preventDefault();
    modal.toggleClass('modal-active');
});

close.on('click', function (e) {
    e.preventDefault();
    modal.removeClass('modal-active');
});
</script>

Conclusion

By implementing a custom jQuery calculator, we significantly improved user interaction on our website. The solution effectively validated input, performed dynamic calculations, and integrated smoothly with Gravity Forms. This approach not only enhanced the user experience but also ensured data integrity and reliability. With the right techniques, such as debouncing and real-time validation, we addressed common issues and created a robust and interactive feature for our users.

Please note: This website is currently under development. I appreciate your patience and understanding as I work on perfecting everything. Thank you!