Enhancing User Interaction with a Dynamic Calculator and Modal Popup

[ ][ ] September 2, 2024

Whats the Problem?

In modern web applications, dynamic user interactions are crucial for providing a seamless experience. Specifically, we needed to implement a calculator that processes user inputs and displays results in real-time, while also integrating a modal popup to present supplementary details. The challenges included ensuring accurate data validation, calculating values based on user input, and managing the modal’s visibility. Proper handling of these aspects is essential to enhance user experience and ensure data integrity.

The Solution


The solution involves a combination of JavaScript and jQuery to create a functional calculator with real-time validation and updates, alongside a modal popup for additional information. Here’s how the solution is structured:

Input Validation

  • Functionality: Validates user inputs to ensure they are numeric and handle comma-separated values.
  • Implementation: Utilizes a debounce function to limit the frequency of validation checks, improving performance and responsiveness. Inputs are validated on keyup and blur events.

Data Calculation

  • Functionality: Calculates various metrics based on user input, including manual hours, automated hours, and associated costs.
  • Implementation: Processes the user inputs to compute values and dynamically updates the display elements with formatted results.

Modal Popup

  • Functionality: Toggles the visibility of a modal popup for displaying additional content.
  • Implementation: Uses jQuery to handle click events for opening and closing the modal. Ensures smooth user interaction by applying and removing the `modal-active` class.

Handling Hidden Fields

  • Functionality: Updates hidden form fields with processed values for further use.
  • Implementation: Dynamically retrieves the form’s ID to select and update hidden fields based on user input.


Here is the JavaScript code that achieves these functionalities:

<script>
( function( $ ) {
    var inputs = $( '.nh-calculator__input' );
    var manualHoursTarget = $( '#manual-hours' );
    var manualCostTarget = $( '#manual-cost' );
    var automatedHoursTarget = $( '#automated-hours' );
    var automatedCostTarget = $( '#automated-cost' );
    var savingsHoursTarget = $( '#savings-hours' );
    var savingsCostTarget = $( '#savings-cost' );

    var button = $( '.nh-calculator__button' );
    var close = $( '.nh-calculator__modal-close' );
    var modal = $( '.nh-calculator__modal-wrapper' );

    var form = $( '.gform_wrapper' );
    var id = form.attr( 'id' ) ? form.attr( 'id' ).toString().split( '' ).pop() : '';
    var hiddenPhysicals = $( '#input_' + id + '_6' );
    var hiddenRate = $( '#input_' + id + '_7' );

    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);
        };
    };

    var validate = debounce( function( e ) {
        var physicals = stripComma( $( '#nh-calculator__physicals' ).val() );
        var rate = $( '#nh-calculator__hourly' ).val() === "" ? '118' : stripComma( $( '#nh-calculator__hourly' ).val() );

        var element = $( e.target );
        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() );
            }

            hiddenPhysicals.val( '' );
            hiddenRate.val( '' );
        } else {
            element.removeClass( 'nhc-border-red' );
            $( '.nh-calculator' ).find( '.nh-calculator__error' ).remove();

            hiddenPhysicals.val( physicals );
            hiddenRate.val( rate );

            agilityCalculate();
        }
    }, 250 );

    function stripComma( value ) {
        return value.replace( /,/g, '' );
    }

    function agilityCalculate() {
        var physicals = stripComma( $( '#nh-calculator__physicals' ).val() );
        var rate = $( '#nh-calculator__hourly' ).val() === "" ? '118' : stripComma( $( '#nh-calculator__hourly' ).val() );

        var manualHours = Math.floor( physicals * 7 / 60 );
        var manualCost = manualHours * rate;
        var automatedHours = Math.floor( physicals * 4 / 60 );
        var automatedCost = automatedHours * rate;
        var savingsHours = manualHours - automatedHours;
        var savingsCost = savingsHours * rate;

        manualHoursTarget.html( manualHours.toLocaleString( 'en-US' ) );
        manualCostTarget.html( '$' + manualCost.toLocaleString( 'en-US' ) );
        automatedHoursTarget.html( automatedHours.toLocaleString( 'en-US' ) );
        automatedCostTarget.html( '$' + automatedCost.toLocaleString( 'en-US' ) );
        savingsHoursTarget.html( savingsHours.toLocaleString( 'en-US' ) );
        savingsCostTarget.html( '$' + savingsCost.toLocaleString( 'en-US' ) );
    }

    inputs.on( 'keyup', validate );
    inputs.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' );
    });
} )( jQuery );
<script>

Conclusion

The provided JavaScript solution integrates a dynamic calculator with real-time validation and calculation capabilities, along with a modal popup for additional information. By leveraging jQuery for event handling and DOM manipulation, the code ensures accurate data processing and user feedback. This approach enhances user experience through interactive elements, providing immediate visual feedback and managing user interactions effectively.

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