dynamic visualization of consumption of chars in input elements with jQuery in relation to the value of a maxlength attribute
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.
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 amaxlength
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 amaxlength
attribute, you need to set the HTML5 conformdata-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>
<!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
- newline-bug in chrome: In Chrome (Linux) counting fails when using \n. [maybe Related: Discussion jQuery Forum]