dynamic visualization of consumption of chars in input elements with jQuery in relation to the value of a maxlength attribute

2016-03-14 00:00:00 IN1 , 2023-04-10 14:16:28 IN1


Update 2018-02-17:
There is a newer and updated Blog Post to this. Please read: jQuery maxlength visual Feedback
[/post/2018/02/17/jquery-maxlength-visual-feedback/]

dynamically visualize a current input char consumption considering the related maxlength attribute value of HTML5 <form> input elements such as<input> and <textarea> with a Progress-Bar using jQuery.

progressBar.jQuery.gif

My Solution shows a progressbar beneath an input element illustrating in realtime how much of the assigned size defined by the element's maxlength (or data-maxlength) attribute has already been used. Per default it appears if current input is about >=50% of the assigned maxlength (you can change this).

It shows three different coloured sections:

  • sectionA 50-69% (lightblue)
  • sectionB 70-99% (orange)
  • sectionC 100% (lightcoral)

The section colors you style by CSS. The section sizes you define by JS (see Modifying).

Overview

Standalone Demos

Implementation

  • Add this CSS into your HTML inside the <head>...</head> section

    <style>
    /* visualizeConsumption
     */
    .visualizeConsumption {
    }
    .progress {
        position: absolute;
    }
        .progress-bar {
            background-color: gray;
        }
        .progress-bar-info {
            background-color: lightblue;
        }
        .progress-bar-warning {
            background-color: orange;
        }
        .progress-bar-danger {
            background-color: lightcoral;
        }
        .progresstext {
        }
    /* other
     */     
    textarea, input, select {
        display: block;
    }       
    </style>
  • Add a the CSS class visualizeConsumption and a maxlength attribute to your input elements, e.g.:

    <input type="text" class="visualizeConsumption" maxlength="10">
    <textarea class="visualizeConsumption" maxlength="100"></textarea>

    Note: As long as select does not provide a maxlength attribute, you need to set the HTML5 conform data-maxlength attribute:

    <select class="visualizeConsumption" data-maxlength="3">…</select>
  • Include jQuery Library Version2* into your HTML

    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js" type="text/javascript"></script>
  • Add "visualizeConsumption" Javascript to your HTML

    <script>
    function visualizeConsumption(oObject,iSectionA,iSectionB,iSectionC){var iSectionA=('undefined'===typeof iSectionA)?50:iSectionA;var iSectionB=('undefined'===typeof iSectionB)?70:iSectionB;var iSectionC=('undefined'===typeof iSectionC)?100:iSectionC;if(null===oObject.val()){return false}$(oObject).on('blur',function(){$('.visualizeConsumptionBar').hide()});var iProgressBarId=oObject.next().attr('data-consumptionBar');if('undefined'===typeof iProgressBarId){var iTimestamp=Date.now();$('<div id="'+iTimestamp+'" data-consumptionBar="'+iTimestamp+'" class="visualizeConsumptionBar progress progress-striped active"><div class="progress-bar"><div class="progresstext"></div></div></div>').insertAfter(oObject);$('.visualizeConsumptionBar').hide();$(oObject).focus();return false}var iMaxlength=(('undefined'!==typeof oObject.attr('maxlength')?oObject.attr('maxlength'):(('undefined'!==typeof oObject.attr('data-maxlength'))?oObject.attr('data-maxlength'):false)));if(false===iMaxlength){return false}var iPercent=(oObject.val().length*100/iMaxlength);(iPercent>=iSectionA)?$('#'+iProgressBarId).show():$('#'+iProgressBarId).hide();(iPercent>=iSectionA&&iPercent<iSectionB)?$('#'+iProgressBarId+' .progress-bar').removeClass('progress-bar-warning progress-bar-danger').addClass('progress-bar-info'):false;(iPercent>=iSectionB&&iPercent<iSectionC)?$('#'+iProgressBarId+' .progress-bar').removeClass('progress-bar-info progress-bar-danger').addClass('progress-bar-warning'):false;(iPercent>=iSectionC)?$('#'+iProgressBarId+' .progress-bar').removeClass('progress-bar-info progress-bar-warning').addClass('progress-bar-danger'):false;$('#'+iProgressBarId).css({'width':oObject.outerWidth()});(iPercent<=100)?$('#'+iProgressBarId+' .progress-bar').css({width:iPercent+'%'}):false;$('#'+iProgressBarId+' .progresstext').text(Math.round(iPercent)+'%');return true}
    </script>
  • Init the bars for inputs having class visualizeConsumption with Javascript event listener

    <script>
        $(".visualizeConsumption").on('click keyup keypress', function() {
            visualizeConsumption($(this));
        });     
    </script>

Full HTML5 example code:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>visualizeConsumption</title>
        <style>         
            /* visualizeConsumption
             */
            .visualizeConsumption {
            }
            .progress {
                position: absolute;
            }
                .progress-bar {
                    background-color: gray;
                }
                .progress-bar-info {
                    background-color: lightblue;
                }
                .progress-bar-warning {
                    background-color: orange;
                }
                .progress-bar-danger {
                    background-color: lightcoral;
                }
                .progresstext {
                }

            /** other
             */
            textarea, input, select {
                display: block;
            }
        </style>
    </head>
    <body>
        <input type="text" class="visualizeConsumption" maxlength="10">

        <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <script>

            // @see https://blog.ueffing.net/post/2016/03/14/dynamic-visualization-of-consumption-of-chars-in-input-elements-with-jquery-in-relation-to-the-value-of-a-maxlength-attribute/
            function visualizeConsumption(oObject,iSectionA,iSectionB,iSectionC){var iSectionA=('undefined'===typeof iSectionA)?50:iSectionA;var iSectionB=('undefined'===typeof iSectionB)?70:iSectionB;var iSectionC=('undefined'===typeof iSectionC)?100:iSectionC;if(null===oObject.val()){return false}$(oObject).on('blur',function(){$('.visualizeConsumptionBar').hide()});var iProgressBarId=oObject.next().attr('data-consumptionBar');if('undefined'===typeof iProgressBarId){var iTimestamp=Date.now();$('<div id="'+iTimestamp+'" data-consumptionBar="'+iTimestamp+'" class="visualizeConsumptionBar progress progress-striped active"><div class="progress-bar"><div class="progresstext"></div></div></div>').insertAfter(oObject);$('.visualizeConsumptionBar').hide();$(oObject).focus();return false}var iMaxlength=(('undefined'!==typeof oObject.attr('maxlength')?oObject.attr('maxlength'):(('undefined'!==typeof oObject.attr('data-maxlength'))?oObject.attr('data-maxlength'):false)));if(false===iMaxlength){return false}var iPercent=(oObject.val().length*100/iMaxlength);(iPercent>=iSectionA)?$('#'+iProgressBarId).show():$('#'+iProgressBarId).hide();(iPercent>=iSectionA&&iPercent<iSectionB)?$('#'+iProgressBarId+' .progress-bar').removeClass('progress-bar-warning progress-bar-danger').addClass('progress-bar-info'):false;(iPercent>=iSectionB&&iPercent<iSectionC)?$('#'+iProgressBarId+' .progress-bar').removeClass('progress-bar-info progress-bar-danger').addClass('progress-bar-warning'):false;(iPercent>=iSectionC)?$('#'+iProgressBarId+' .progress-bar').removeClass('progress-bar-info progress-bar-warning').addClass('progress-bar-danger'):false;$('#'+iProgressBarId).css({'width':oObject.outerWidth()});(iPercent<=100)?$('#'+iProgressBarId+' .progress-bar').css({width:iPercent+'%'}):false;$('#'+iProgressBarId+' .progresstext').text(Math.round(iPercent)+'%');return true}

            // init
            $(document).ready(function(){
                $(".visualizeConsumption").on('click keyup keypress', function() {visualizeConsumption($(this));});    
            });    
        </script>
    </body>
</html>

Supported Web Form Elements

Works for the following Web Form Elements:

  • <imput type="text"..>
  • <imput type="email"..>
  • <imput type="password"..>
  • <imput type="search"..>
  • <imput type="tel"..>
  • <imput type="url"..>
  • <textarea..>
  • <select..>

Note: As long as select does not provide a maxlength attribute, you need to set the HTML5 conform data-maxlength attribute.

Modifying

Styling

edit the following CSS to your needs to style the visualizeConsumption bar

/* CSS */
.visualizeConsumption {/* example: */
    /*height: 10px;*/
    /*bottom: -25px;*/
    /*z-index: -1;*/
    /*opacity: 0.3;*/
}
.progress-bar {/* default color */
    background-color: gray;
}
.progress-bar-info {/* color first section */
    background-color: lightblue;
}
.progress-bar-warning {/* color second section */
    background-color: orange;
}
.progress-bar-danger {/* color third section */
    background-color: lightcoral;
}
.progresstext {
    position: absolute;/* makes text stand left side fixed */
}

Change section sizes

you can change the section sizes by the init JS script. Example:

$(".visualizeConsumption").on('click keyup keypress', function() {
        visualizeConsumption($(this), 1, 80, 90);
});     

Here, the first section (lightblue) would start at 1%, the second one (orange) at 80% and the third one (lightcoral) at 90%.

Javascript Code

/**
 * shows a progressbar beneath an input, textarea or select element illustrating 
 * in realtime how much of the value of maxlength attribute has already been used. 
 * requires jQuery.
 * input/textarea must have a maxlength, select must have a data-maxlength attribute set.
 * @see https://blog.ueffing.net/post/2016/03/14/dynamic-visualization-of-consumption-of-chars-in-input-elements-with-jquery-in-relation-to-the-value-of-a-maxlength-attribute/
 *          
 * @param {Object} oObject element. MANDATORY
 * @param {Integer} iSectionA first section; default=50. OPTIONAL
 * @param {Integer} iSectionB second section; default=70. OPTIONAL
 * @param {Integer} iSectionC third section; default=100. OPTIONAL
 * @returns {Boolean} success
 */
function visualizeConsumption(oObject, iSectionA, iSectionB, iSectionC) {

    // default fallback settings
    var iSectionA = ('undefined' === typeof iSectionA) ? 50 : iSectionA;
    var iSectionB = ('undefined' === typeof iSectionB) ? 70 : iSectionB;
    var iSectionC = ('undefined' === typeof iSectionC) ? 100 : iSectionC;

    if (null === oObject.val())
    {
        return false;
    }

    // hide all bars on blur
    $(oObject).on('blur', function(){$('.visualizeConsumptionBar').hide();});

    // identify next bar element
    var iProgressBarId = oObject.next().attr('data-consumptionBar');

    // dynamically add bar once
    if ('undefined' === typeof iProgressBarId)
    {      
        var iTimestamp = Date.now();
        $('<div id="' + iTimestamp + '" data-consumptionBar="' + iTimestamp + '" class="visualizeConsumptionBar progress progress-striped active"><div class="progress-bar"><div class="progresstext"></div></div></div>').insertAfter(oObject);
        $('.visualizeConsumptionBar').hide();
        $(oObject).focus();

        return false;
    }

    // get maxlength (or data-maxlength) value from input field
    var iMaxlength = (('undefined' !== typeof oObject.attr('maxlength') ? oObject.attr('maxlength') : (('undefined' !== typeof oObject.attr('data-maxlength')) ? oObject.attr('data-maxlength') : false)));
    if (false === iMaxlength)
    {
        return false;
    }

    // calc progress scale
    var iPercent = (oObject.val().length * 100 / iMaxlength);

    (iPercent >= iSectionA) ? $('#' + iProgressBarId).show() : $('#' + iProgressBarId).hide();                     
    (iPercent >= iSectionA && iPercent < iSectionB) ? $('#' + iProgressBarId + ' .progress-bar').removeClass('progress-bar-warning progress-bar-danger').addClass('progress-bar-info') : false;
    (iPercent >= iSectionB && iPercent < iSectionC) ? $('#' + iProgressBarId + ' .progress-bar').removeClass('progress-bar-info progress-bar-danger').addClass('progress-bar-warning') : false;
    (iPercent >= iSectionC) ? $('#' + iProgressBarId + ' .progress-bar').removeClass('progress-bar-info progress-bar-warning').addClass('progress-bar-danger') : false;

    // adjust widths, add text
    $('#' + iProgressBarId).css({'width':oObject.outerWidth()});                
    (iPercent <= 100) ? $('#' + iProgressBarId + ' .progress-bar').css({width: iPercent + '%'}) : false;
    $('#' + iProgressBarId + ' .progresstext').text(Math.round(iPercent) + '%');

    return true;
}

Known Issues


Links

This website uses Cookies to provide you with the best possible service. Please see our Privacy Policy for more information. Click the check box below to accept cookies. Then confirm with a click on "Save".