diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php
index 849b0f73fafde49df56a29b4903721c72f26be43..cca8fb65333f92ada2c2c70adca78e200537a075 100644
--- a/extension/qfq/qfq/AbstractBuildForm.php
+++ b/extension/qfq/qfq/AbstractBuildForm.php
@@ -727,6 +727,7 @@ abstract class AbstractBuildForm {
         $textarea = '';
         $attribute = '';
         $class = 'form-control';
+        $elementCharacterCount = '';
 
         $typeAheadUrlParam = $this->typeAheadBuildParam($formElement);
         if ($typeAheadUrlParam != '') {
@@ -737,15 +738,43 @@ abstract class AbstractBuildForm {
             $attribute .= Support::doAttribute(DATA_TYPEAHEAD_MINLENGTH, $formElement[FE_TYPEAHEAD_MINLENGTH]);
         }
 
+        if (isset($formElement[FE_CHARACTER_COUNT_WRAP])) {
+            $class .= ' ' . CLASS_CHARACTER_COUNT;
+            $attribute .= Support::doAttribute(DATA_CHARACTER_COUNT_ID, $formElement[FE_HTML_ID] . HTML_ID_EXTENSION_CHARACTER_COUNT);
+            $attributeCC = Support::doAttribute('id', $formElement[FE_HTML_ID] . HTML_ID_EXTENSION_CHARACTER_COUNT);
+
+            $classCC = ($formElement[FE_CHARACTER_COUNT_WRAP] == '') ? Support::doAttribute('class', 'qfq-cc-style') : '';
+            $elementCharacterCount = "<span $attributeCC $classCC></span>";
+
+            if ($formElement[FE_CHARACTER_COUNT_WRAP] != '') {
+                $arr = explode('|', $formElement[FE_CHARACTER_COUNT_WRAP], 2);
+                $arr[] = '';
+                $arr[] = ''; //skip check that at least 2 elements exist
+                $elementCharacterCount = $arr[0] . $elementCharacterCount . $arr[1];
+            }
+        }
+
         $attribute .= Support::doAttribute('id', $formElement[FE_HTML_ID]);
         $attribute .= Support::doAttribute('name', $htmlFormElementName);
         $attribute .= Support::doAttribute('class', $class);
 
+
         if (isset($formElement[FE_RETYPE_SOURCE_NAME])) {
             $htmlFormElementNamePrimary = str_replace(RETYPE_FE_NAME_EXTENSION, '', $htmlFormElementName);
             $attribute .= Support::doAttribute('data-match', '[name=' . str_replace(':', '\\:', $htmlFormElementNamePrimary) . ']');
         }
 
+        $this->adjustMaxLength($formElement);
+
+        if ($formElement[FE_MAX_LENGTH] > 0 && $value !== '') {
+            // crop string only if it's not empty (substr returns false on empty strings)
+            $value = substr($value, 0, $formElement[FE_MAX_LENGTH]);
+        }
+        // 'maxLength' needs an upper 'L': naming convention for DB tables!
+        if ($formElement[FE_MAX_LENGTH] > 0) {
+            $attribute .= Support::doAttribute('maxlength', $formElement[FE_MAX_LENGTH], false);
+        }
+
         // Check for input type 'textarea'.
         $colsRows = explode(',', $formElement['size'], 2);
         if (count($colsRows) === 2) {
@@ -759,15 +788,7 @@ abstract class AbstractBuildForm {
         } else {
             $htmlTag = '<input';
 
-            $this->adjustMaxLength($formElement);
-
-            if ($formElement[FE_MAX_LENGTH] > 0 && $value !== '') {
-                // crop string only if it's not empty (substr returns false on empty strings)
-                $value = substr($value, 0, $formElement[FE_MAX_LENGTH]);
-            }
-
-            // 'maxLength' needs an upper 'L': naming convention for DB tables!
-            $attribute .= $this->getAttributeList($formElement, ['type', 'size', 'maxLength']);
+            $attribute .= $this->getAttributeList($formElement, ['type', 'size']);
             $attribute .= Support::doAttribute('value', htmlentities($value), false);
         }
 
@@ -781,7 +802,7 @@ abstract class AbstractBuildForm {
 
         $json = $this->getFormElementForJson($htmlFormElementName, $value, $formElement);
 
-        return "$htmlTag $attribute>$textarea" . $this->getHelpBlock();
+        return "$htmlTag $attribute>$textarea" . $elementCharacterCount . $this->getHelpBlock();
 
     }
 
diff --git a/extension/qfq/tests/phpunit/BuildFormPlainTest.php b/extension/qfq/tests/phpunit/BuildFormPlainTest.php
index 2546d02f120e43f0802fb743a3e7699e334b2bae..c9553ae3f737389c0332349aa68be5c3307de382 100644
--- a/extension/qfq/tests/phpunit/BuildFormPlainTest.php
+++ b/extension/qfq/tests/phpunit/BuildFormPlainTest.php
@@ -83,32 +83,32 @@ class BuildFormPlainTest extends AbstractDatabaseTest {
         $label['123-l'][API_ELEMENT_CONTENT] = '<label for="name:1" class="control-label" >Name</label>';
 
         $result = $build->buildInput($formElement, 'name:1', '', $json);
-        $this->assertEquals('<input id="123" name="name:1" class="form-control" type="input" maxlength="255" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', API_ELEMENT_UPDATE => $label], $json);
 
         // CheckType
         $formElement['checkType'] = SANITIZE_ALLOW_MIN_MAX;
         $formElement['checkPattern'] = '1|10';
         $result = $build->buildInput($formElement, 'name:1', '', $json);
-        $this->assertEquals('<input id="123" name="name:1" class="form-control" type="input" maxlength="255" value="" min="1" max="10" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" min="1" max="10" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', 'disabled' => false, API_ELEMENT_UPDATE => $label], $json);
 
         $formElement['checkType'] = SANITIZE_ALLOW_PATTERN;
         $formElement['checkPattern'] = '^[a-z]*$';
         $result = $build->buildInput($formElement, 'name:1', '', $json);
-        $this->assertEquals('<input id="123" name="name:1" class="form-control" type="input" maxlength="255" value="" pattern="^[a-z]*$" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" pattern="^[a-z]*$" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', 'disabled' => false, API_ELEMENT_UPDATE => $label], $json);
 
         $formElement['checkType'] = SANITIZE_ALLOW_DIGIT;
         $formElement['checkPattern'] = '';
         $result = $build->buildInput($formElement, 'name:1', '', $json);
-        $this->assertEquals('<input id="123" name="name:1" class="form-control" type="input" maxlength="255" value="" pattern="^[\d]*$" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" pattern="^[\d]*$" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', 'disabled' => false, API_ELEMENT_UPDATE => $label], $json);
 
         $formElement['checkType'] = SANITIZE_ALLOW_EMAIL;
         $formElement['checkPattern'] = '';
         $result = $build->buildInput($formElement, 'name:1', '', $json);
-        $this->assertEquals('<input id="123" name="name:1" class="form-control" type="input" maxlength="255" value="" pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" value="" pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', 'disabled' => false, API_ELEMENT_UPDATE => $label], $json);
 
         $formElement['checkType'] = '';
@@ -119,13 +119,13 @@ class BuildFormPlainTest extends AbstractDatabaseTest {
         $formElement['size'] = 40;
         $formElement['maxLength'] = 40;
         $result = $build->buildInput($formElement, 'name:1', '', $json);
-        $this->assertEquals('<input id="123" name="name:1" class="form-control" type="input" size="40" maxlength="40" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="40" type="input" size="40" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', 'disabled' => false, API_ELEMENT_UPDATE => $label], $json);
 
         // maxlength bigger than physical spec:
         $formElement['maxLength'] = 1000;
         $result = $build->buildInput($formElement, 'name:1', '', $json);
-        $this->assertEquals('<input id="123" name="name:1" class="form-control" type="input" size="40" maxlength="255" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" size="40" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => '', 'disabled' => false, API_ELEMENT_UPDATE => $label], $json);
 
         // no size, no maxlength and column not in primary table
@@ -139,7 +139,7 @@ class BuildFormPlainTest extends AbstractDatabaseTest {
         // no size,  given maxlength and column not in primary table
         $formElement2['maxLength'] = '10';
         $result = $build->buildInput($formElement2, 'specialname:1', '', $json);
-        $this->assertEquals('<input id="123" name="specialname:1" class="form-control" type="input" maxlength="10" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="specialname:1" class="form-control" maxlength="10" type="input" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
 
         // size given, no maxlength and column not in primary table
         $formElement2['maxLength'] = '';
@@ -151,25 +151,26 @@ class BuildFormPlainTest extends AbstractDatabaseTest {
         $formElement2['maxLength'] = '20';
         $formElement2['size'] = '10';
         $result = $build->buildInput($formElement2, 'specialname:1', '', $json);
-        $this->assertEquals('<input id="123" name="specialname:1" class="form-control" type="input" size="10" maxlength="20" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="specialname:1" class="form-control" maxlength="20" type="input" size="10" value="" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
 
 
         // Explicit: further
         $formElement['tooltip'] = 'Nice Tooltip';
         $formElement['placeholder'] = 'Please type a name';
         $result = $build->buildInput($formElement, 'name:1', 'Hello World', $json);
-        $this->assertEquals('<input id="123" name="name:1" class="form-control" type="input" size="40" maxlength="255" value="Hello World" placeholder="Please type a name" title="Nice Tooltip" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<input id="123" name="name:1" class="form-control" maxlength="255" type="input" size="40" value="Hello World" placeholder="Please type a name" title="Nice Tooltip" data-hidden="no" data-disabled="no" data-required="no" ><div class="help-block with-errors hidden"></div>', $result);
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => 'Hello World', 'disabled' => false, API_ELEMENT_UPDATE => $label], $json);
 
         // textarea
         $formElement['size'] = '40,10';
         $result = $build->buildInput($formElement, 'name:1', 'Hello World', $json);
-        $this->assertEquals('<textarea id="123" name="name:1" class="form-control" cols="40" rows="10" placeholder="Please type a name" title="Nice Tooltip" data-hidden="no" data-disabled="no" data-required="no" >Hello World</textarea><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<textarea id="123" name="name:1" class="form-control" maxlength="255" cols="40" rows="10" placeholder="Please type a name" title="Nice Tooltip" data-hidden="no" data-disabled="no" data-required="no" >Hello World</textarea><div class="help-block with-errors hidden"></div>', $result);
+
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => 'Hello World', 'disabled' => false, API_ELEMENT_UPDATE => $label], $json);
 
         $formElement['size'] = ' 40     , 10 ';
         $result = $build->buildInput($formElement, 'name:1', 'Hello World', $json);
-        $this->assertEquals('<textarea id="123" name="name:1" class="form-control" cols="40" rows="10" placeholder="Please type a name" title="Nice Tooltip" data-hidden="no" data-disabled="no" data-required="no" >Hello World</textarea><div class="help-block with-errors hidden"></div>', $result);
+        $this->assertEquals('<textarea id="123" name="name:1" class="form-control" maxlength="255" cols="40" rows="10" placeholder="Please type a name" title="Nice Tooltip" data-hidden="no" data-disabled="no" data-required="no" >Hello World</textarea><div class="help-block with-errors hidden"></div>', $result);
         $this->assertEquals([FE_MODE_HIDDEN => '', 'disabled' => false, FE_MODE_REQUIRED => '', 'form-element' => 'name:1', 'value' => 'Hello World', 'disabled' => false, API_ELEMENT_UPDATE => $label], $json);
     }