-
-
-
i; i++) {
+ if (this.hasOwnProperty(sets[i]) && this[sets[i]] > 0) {
+ mods = mods + 1;
+ }
+ }
+
+ score += this.calc(value, /[a-z]/g, this.lowercase, mods);
+ score += this.calc(value, /[A-Z]/g, this.uppercase, mods);
+ score += this.calc(value, /[0-9]/g, this.numbers, mods);
+ score += this.calc(value, /[\$\!\#\?\=\;\:\*\-\_\€\%\&\(\)\`\´]/g, this.special, mods);
+ if (mods == 1) {
+ score += value.length > this.length ? 100 : 100 / this.length * value.length;
+ } else {
+ score += value.length > this.length ? (100 / mods) : (100 / mods) / this.length * value.length;
+ }
+
+ return score;
+ }
+
+ calc(value, pattern, length, mods) {
+ const count = value.match(pattern);
+ if (count && count.length > length && length != 0) {
+ return 100 / mods;
+ }
+ if (count && length > 0) {
+ return (100 / mods) / length * count.length;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ class JoomlaFieldPassword extends HTMLElement {
+ static get observedAttributes() {
+ return ['min-length', 'min-integers', 'min-symbols', 'min-uppercase', 'min-lowercase', 'reveal', 'text-show', 'text-hide', 'text-complete', 'text-incomplete'];
+ }
+
+ get minLength() { return parseInt(this.getAttribute('min-length') || 0); }
+ get minIntegers() { return parseInt(this.getAttribute('min-integers') || 0); }
+ get minSymbols() { return parseInt(this.getAttribute('min-symbols') || 0); }
+ get minUppercase() { return parseInt(this.getAttribute('min-uppercase') || 0); }
+ get minLowercase() { return parseInt(this.getAttribute('min-lowercase') || 0); }
+ get reveal() { return this.getAttribute('reveal') || false; }
+ get showText() { return this.getAttribute('text-show') || 'Show'; }
+ get hideText() { return this.getAttribute('text-hide') || 'Hide'; }
+ get completeText() { return this.getAttribute('text-complete') || 'Password meets site\'s requirements'; }
+ get incompleteText() { return this.getAttribute('text-incomplete') || 'Password does not meet site\'s requirements'; }
+
+ // attributeChangedCallback(attr, oldValue, newValue) {}
+
+ constructor() {
+ super();
+
+ if (!window.Joomla) {
+ throw new Error('Joomla API is not iniatiated!')
+ }
+
+ this.input = this.querySelector('input');
+
+ if (!this.input) {
+ throw new Error('Joomla Password field requires an input element!')
+ }
+
+ this.meterLabel = ''
+ this.meter = ''
+ }
+
+ connectedCallback() {
+ if (this.reveal === 'true') {
+ const parent = document.createElement('div');
+ const parentSpan = document.createElement('span');
+ const firstSpan = document.createElement('span');
+ const secondSpan = document.createElement('span');
+
+ parent.classList.add('input-group-append');
+ parentSpan.setAttribute('class', 'input-group-text');
+ firstSpan.setAttribute('class', 'fa fa-eye');
+ firstSpan.setAttribute('aria-hidden', 'true');
+ secondSpan.setAttribute('class', 'sr-only');
+ secondSpan.innerText = this.showText;
+
+ parentSpan.appendChild(firstSpan);
+ parentSpan.appendChild(secondSpan);
+ parent.appendChild(parentSpan);
+
+ let groupInput = this.querySelector('.input-group');
+
+ if (!groupInput) {
+ groupInput = document.createElement('div');
+ groupInput.classList.add('input-group');
+
+ groupInput.appendChild(this.input);
+ this.appendChild(groupInput);
+ }
+
+ groupInput.appendChild(parent);
+
+ const that = this;
+
+ this.input = this.querySelector('input');
+
+ // @TODO Remove Font awesome dependency
+ // @TODO Remove Bootstrap dependency
+ firstSpan.addEventListener('click', () => {
+
+ if (firstSpan.classList.contains('fa-eye')) {
+ // Update the icon class
+ firstSpan.classList.remove('fa-eye');
+ firstSpan.classList.add('fa-eye-slash');
+
+ // Update the input type
+ that.input.type = 'text';
+
+ // Update the text for screenreaders
+ secondSpan.innerText = that.showText;
+ } else {
+ // Update the icon class
+ firstSpan.classList.add('fa-eye');
+ firstSpan.classList.remove('fa-eye-slash');
+
+ // Update the input type
+ that.input.type = 'password';
+
+ // Update the text for screenreaders
+ secondSpan.innerText = that.hideText;
+ }
+ });
+ }
+
+ // Meter is enabled
+ // @TODO Remove Bootstrap dependency
+ if (this.minLength && this.minLength > 0
+ ||this.minIntegers && this.minIntegers > 0
+ ||this.minSymbols && this.minSymbols > 0
+ ||this.minUppercase && this.minUppercase > 0
+ ||this.minLowercase && this.minLowercase > 0
+ ) {
+ let startClass = '';
+ let initialVal = '';
+ let el;
+
+ if (!this.input.value.length) {
+ startClass = ' bg-danger';
+ initialVal = 0;
+ }
+
+ const i = Math.random().toString(36).substr(2, 9);
+
+ /** Create a progress meter and the label **/
+ const meter = document.createElement('div');
+ meter.setAttribute('class', 'progress');
+
+ this.meter = document.createElement('div');
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated' + startClass);
+ this.meter.style.width = 0 + initialVal;
+ this.meter.max = 100;
+ this.meter.setAttribute('aria-describedby', 'password-' + i);
+ meter.appendChild(this.meter);
+
+ this.meterLabel = document.createElement('div');
+ this.meterLabel.setAttribute('class', 'text-xs-center');
+ this.meterLabel.setAttribute('id', 'password-' + i);
+
+ this.insertAdjacentElement('beforeend', this.meterLabel);
+ this.insertAdjacentElement('beforeend', meter);
+
+ /** Add a data attribute for the required **/
+ if (this.input.value.length > 0) {
+ this.input.setAttribute('required', '');
+ }
+
+ /** Add a listener for input data change **/
+ this.input.addEventListener('keyup', this.getMeter.bind(this));
+
+ // Set the validation handler
+ // @TODO refactor the validation.js to reflect the changes here!
+ this.setAttribute('validation-handler', 'password-strength' + '_' + Math.random().toString(36).substr(2, 9));
+
+ if (document.formvalidator) {
+ document.formvalidator.setHandler(this.getAttribute('validation-handler'), this.handler.bind(this));
+ }
+ }
+ }
+
+ disconnectedCallback() {
+
+ }
+
+ /** Method to check the input and set the meter **/
+ getMeter() {
+
+ if (!this.meter || !this.meterLabel) {
+ return;
+ }
+
+ const strength = new PasswordStrength({
+ lowercase: this.minLowercase ? this.minLowercase : 0,
+ uppercase: this.minUppercase ? this.minUppercase : 0,
+ numbers : this.minIntegers ? this.minIntegers : 0,
+ special : this.minSymbols ? this.minSymbols : 0,
+ length : this.minLength ? this.minLength : 4
+ });
+
+ const score = strength.getScore(this.input.value);
+
+ if (score > 79) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.completeText;
+ }
+ if (score > 64 && score < 80) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score > 50 && score < 65) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score > 40 && score < 51) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score < 41) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-danger');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score === 100) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-success');
+ }
+ this.meter.style.width = score + '%';
+
+ if (!this.input.value.length) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated');
+ this.meterLabel.innerHTML = '';
+ this.input.setAttribute('required', '');
+ }
+ }
+
+ handler(value) {
+ const strength = new PasswordStrength({
+ lowercase: this.minLowercase ? this.minLowercase : 0,
+ uppercase: this.minUppercase ? this.minUppercase : 0,
+ numbers : this.minIntegers ? this.minIntegers : 0,
+ special : this.minSymbols ? this.minSymbols : 0,
+ length : this.minLength ? this.minLength : 4
+ });
+
+ if (strength.getScore(value) === 100) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ customElements.define('joomla-field-password', JoomlaFieldPassword);
+
+})(customElements);
diff --git a/layouts/joomla/form/field/password.php b/layouts/joomla/form/field/password.php
index 6c9a831b05866..baf25f62cd396 100644
--- a/layouts/joomla/form/field/password.php
+++ b/layouts/joomla/form/field/password.php
@@ -50,7 +50,6 @@
if ($meter)
{
HTMLHelper::_('behavior.formvalidator');
- HTMLHelper::_('script', 'system/fields/passwordstrength.min.js', array('version' => 'auto', 'relative' => true));
$class = 'js-password-strength ' . $class;
@@ -60,12 +59,7 @@
}
}
-HTMLHelper::_('script', 'system/fields/passwordview.min.js', array('version' => 'auto', 'relative' => true));
-
-Text::script('JFIELD_PASSWORD_INDICATE_INCOMPLETE');
-Text::script('JFIELD_PASSWORD_INDICATE_COMPLETE');
-Text::script('JSHOW');
-Text::script('JHIDE');
+HTMLHelper::_('webcomponent', 'system/webcomponents/joomla-field-password.js', ['version' => 'auto', 'relative' => true]);
$attributes = array(
strlen($hint) ? 'placeholder="' . htmlspecialchars($hint, ENT_COMPAT, 'UTF-8') . '"' : '',
@@ -77,26 +71,27 @@
!empty($maxLength) ? 'maxlength="' . $maxLength . '"' : '',
$required ? 'required' : '',
$autofocus ? 'autofocus' : '',
- !empty($minLength) ? 'data-min-length="' . $minLength . '"' : '',
- !empty($minIntegers) ? 'data-min-integers="' . $minIntegers . '"' : '',
- !empty($minSymbols) ? 'data-min-symbols="' . $minSymbols . '"' : '',
- !empty($minUppercase) ? 'data-min-uppercase="' . $minUppercase . '"' : '',
- !empty($minLowercase) ? 'data-min-lowercase="' . $minLowercase . '"' : '',
- !empty($forcePassword) ? 'data-min-force="' . $forcePassword . '"' : '',
);
+\Joomla\CMS\Factory::getDocument()->addStyleDeclaration('
+joomla-field-password > .progress {
+ max-width: 277px;
+}
+')
?>
diff --git a/media/system/js/fields/passwordstrength.js b/media/system/js/fields/passwordstrength.js
deleted file mode 100644
index 44ab98e70ef9e..0000000000000
--- a/media/system/js/fields/passwordstrength.js
+++ /dev/null
@@ -1,186 +0,0 @@
-"use strict";
-
-/**
- * PasswordStrength script by Thomas Kjaergaard
- * License: MIT
- * Repo: https://github.com/tkjaergaard/Password-Strength
- */
-var PasswordStrength;
-
-PasswordStrength = (function() {
- function PasswordStrength(settings) {
- this.lowercase = settings.lowercase || 0;
- this.uppercase = settings.uppercase || 0;
- this.numbers = settings.numbers || 0;
- this.special = settings.special || 0;
- this.length = settings.length || 4;
- }
-
- PasswordStrength.prototype.getScore = function(value) {
- var score = 0, mods = 0;
- var sets = ['lowercase', 'uppercase', 'numbers', 'special', 'length'];
- for (var i = 0, l = sets.length; l>i; i++) {
- if (this.hasOwnProperty(sets[i]) && this[sets[i]] > 0) {
- mods = mods + 1;
- }
- }
-
- score += this.calc(value, /[a-z]/g, this.lowercase, mods);
- score += this.calc(value, /[A-Z]/g, this.uppercase, mods);
- score += this.calc(value, /[0-9]/g, this.numbers, mods);
- score += this.calc(value, /[\$\!\#\?\=\;\:\*\-\_\€\%\&\(\)\`\´]/g, this.special, mods);
- if (mods == 1) {
- score += value.length > this.length ? 100 : 100 / this.length * value.length;
- } else {
- score += value.length > this.length ? (100 / mods) : (100 / mods) / this.length * value.length;
- }
-
- return score;
- };
-
- PasswordStrength.prototype.calc = function(value, pattern, length, mods) {
- var count;
- count = value.match(pattern);
- if (count && count.length > length && length != 0) {
- return 100 / mods;
- }
- if (count && length > 0) {
- return (100 / mods) / length * count.length;
- } else {
- return 0;
- }
-
- };
-
- return PasswordStrength;
-
-})();
-
-/**
- * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
- * @license GNU General Public License version 2 or later; see LICENSE.txt
- */
-document.addEventListener('DOMContentLoaded', function(){
- "use strict";
-
- /** Method to check the input and set the meter **/
- var getMeter = function(element) {
- var $minLength = element.getAttribute('data-min-length'),
- $minIntegers = element.getAttribute('data-min-integers'),
- $minSymbols = element.getAttribute('data-min-symbols'),
- $minUppercase = element.getAttribute('data-min-uppercase'),
- $minLowercase = element.getAttribute('data-min-lowercase'),
- meter = document.querySelector('.progress-bar');
-
- var strength = new PasswordStrength({
- lowercase: $minLowercase ? $minLowercase : 0,
- uppercase: $minUppercase ? $minUppercase : 0,
- numbers: $minIntegers ? $minIntegers : 0,
- special: $minSymbols ? $minSymbols : 0,
- length: $minLength ? $minLength : 4
- });
-
- var score = strength.getScore(element.value),
- i = meter.getAttribute('aria-describedby').replace( /^\D+/g, ''),
- label = element.parentNode.parentNode.querySelector('#password-' + i);
-
- if (score > 79){
- meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
- label.innerHTML = Joomla.JText._('JFIELD_PASSWORD_INDICATE_COMPLETE');
- }
- if (score > 64 && score < 80){
- meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
- label.innerHTML = Joomla.JText._('JFIELD_PASSWORD_INDICATE_INCOMPLETE');
- }
- if (score > 50 && score < 65){
- meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
- label.innerHTML = Joomla.JText._('JFIELD_PASSWORD_INDICATE_INCOMPLETE');
- }
- if (score > 40 && score < 51){
- meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
- label.innerHTML = Joomla.JText._('JFIELD_PASSWORD_INDICATE_INCOMPLETE');
- }
- if (score < 41){
- meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-danger');
- label.innerHTML = Joomla.JText._('JFIELD_PASSWORD_INDICATE_INCOMPLETE');
- }
- if (score === 100){
- meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-success');
- }
- meter.style.width = score + '%';
-
- if (!element.value.length) {
- meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated');
- label.innerHTML = '';
- element.setAttribute('required', '');
- }
- };
-
- var fields = document.querySelectorAll('.js-password-strength');
-
- /** Loop through the fields **/
- for (var i = 0, l = fields.length; i
0) {
- fields[i].setAttribute('required', true);
- }
-
- /** Add a listener for input data change **/
- fields[i].addEventListener('keyup', function(event) {
- getMeter(event.target);
- });
- }
-
- /** Set a handler for the validation script **/
- if (fields[0]) {
- document.formvalidator.setHandler('password-strength', function(value) {
-
- var returnedValue = false,
- fields = document.querySelectorAll('.js-password-strength'),
- $minLength = fields[0].getAttribute('data-min-length'),
- $minIntegers = fields[0].getAttribute('data-min-integers'),
- $minSymbols = fields[0].getAttribute('data-min-symbols'),
- $minUppercase = fields[0].getAttribute('data-min-uppercase'),
- $minLowercase = fields[0].getAttribute('data-min-lowercase');
-
- var strength = new PasswordStrength({
- lowercase: $minLowercase ? $minLowercase : 0,
- uppercase: $minUppercase ? $minUppercase : 0,
- numbers: $minIntegers ? $minIntegers : 0,
- special: $minSymbols ? $minSymbols : 0,
- length: $minLength ? $minLength : 4
- });
-
- var score = strength.getScore(value);
- if (score === 100 ) returnedValue = true;
-
- return returnedValue;
- });
- }
-});
diff --git a/media/system/js/fields/passwordstrength.min.js b/media/system/js/fields/passwordstrength.min.js
deleted file mode 100644
index 4bb435464d1c9..0000000000000
--- a/media/system/js/fields/passwordstrength.min.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";var PasswordStrength;PasswordStrength=function(){function e(e){this.lowercase=e.lowercase||0,this.uppercase=e.uppercase||0,this.numbers=e.numbers||0,this.special=e.special||0,this.length=e.length||4}return e.prototype.getScore=function(e){for(var t=0,r=0,s=["lowercase","uppercase","numbers","special","length"],a=0,n=s.length;n>a;a++)this.hasOwnProperty(s[a])&&this[s[a]]>0&&(r+=1);return t+=this.calc(e,/[a-z]/g,this.lowercase,r),t+=this.calc(e,/[A-Z]/g,this.uppercase,r),t+=this.calc(e,/[0-9]/g,this.numbers,r),t+=this.calc(e,/[\$\!\#\?\=\;\:\*\-\_\€\%\&\(\)\`\´]/g,this.special,r),t+=1==r?e.length>this.length?100:100/this.length*e.length:e.length>this.length?100/r:100/r/this.length*e.length},e.prototype.calc=function(e,t,r,s){var a;return(a=e.match(t))&&a.length>r&&0!=r?100/s:a&&r>0?100/s/r*a.length:0},e}(),document.addEventListener("DOMContentLoaded",function(){for(var e=document.querySelectorAll(".js-password-strength"),t=0,r=e.length;t0&&e[t].setAttribute("required",!0),e[t].addEventListener("keyup",function(e){var t,r,s,a,n,i,o,g,l,c;t=e.target,r=t.getAttribute("data-min-length"),s=t.getAttribute("data-min-integers"),a=t.getAttribute("data-min-symbols"),n=t.getAttribute("data-min-uppercase"),i=t.getAttribute("data-min-lowercase"),o=document.querySelector(".progress-bar"),g=new PasswordStrength({lowercase:i||0,uppercase:n||0,numbers:s||0,special:a||0,length:r||4}).getScore(t.value),l=o.getAttribute("aria-describedby").replace(/^\D+/g,""),c=t.parentNode.parentNode.querySelector("#password-"+l),g>79&&(o.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-warning"),c.innerHTML=Joomla.JText._("JFIELD_PASSWORD_INDICATE_COMPLETE")),g>64&&g<80&&(o.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-warning"),c.innerHTML=Joomla.JText._("JFIELD_PASSWORD_INDICATE_INCOMPLETE")),g>50&&g<65&&(o.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-warning"),c.innerHTML=Joomla.JText._("JFIELD_PASSWORD_INDICATE_INCOMPLETE")),g>40&&g<51&&(o.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-warning"),c.innerHTML=Joomla.JText._("JFIELD_PASSWORD_INDICATE_INCOMPLETE")),g<41&&(o.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-danger"),c.innerHTML=Joomla.JText._("JFIELD_PASSWORD_INDICATE_INCOMPLETE")),100===g&&o.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-success"),o.style.width=g+"%",t.value.length||(o.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated"),c.innerHTML="",t.setAttribute("required",""))})}e[0]&&document.formvalidator.setHandler("password-strength",function(e){var t=!1,r=document.querySelectorAll(".js-password-strength"),s=r[0].getAttribute("data-min-length"),a=r[0].getAttribute("data-min-integers"),n=r[0].getAttribute("data-min-symbols"),i=r[0].getAttribute("data-min-uppercase"),o=r[0].getAttribute("data-min-lowercase");return 100===new PasswordStrength({lowercase:o||0,uppercase:i||0,numbers:a||0,special:n||0,length:s||4}).getScore(e)&&(t=!0),t})});
\ No newline at end of file
diff --git a/media/system/js/fields/passwordview.js b/media/system/js/fields/passwordview.js
deleted file mode 100644
index 901d75ef2be0b..0000000000000
--- a/media/system/js/fields/passwordview.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
- * @license GNU General Public License version 2 or later; see LICENSE.txt
- */
-
-/**
- * Field switcher
- */
-
-(function() {
- 'use strict';
-
- document.addEventListener('DOMContentLoaded', function() {
-
- var passwordInputs = document.getElementsByTagName('input');
-
- for (var i = 0, l = passwordInputs.length; i < l; i++) {
-
- if (passwordInputs[i].getAttribute('type') === 'password') {
-
- var inputGroup = passwordInputs[i].parentNode.querySelector('.input-group-addon');
-
- if (inputGroup) {
- inputGroup.addEventListener('click', function(e) {
-
- var target = this.querySelector('.fa'),
- input = this.parentNode.querySelector('input'),
- srText = target.nextElementSibling;
-
- if (target.classList.contains('fa-eye')) {
- // Update the icon class
- target.classList.remove('fa-eye');
- target.classList.add('fa-eye-slash');
-
- // Update the input type
- input.type = 'text';
-
- // Updat the text for screenreaders
- srText.innerText = Joomla.JText._('JSHOW');
- }
- else {
- // Update the icon class
- target.classList.add('fa-eye');
- target.classList.remove('fa-eye-slash');
-
- // Update the input type
- input.type = 'password';
-
- // Updat the text for screenreaders
- srText.innerText = Joomla.JText._('JHIDE');
- }
- });
- }
-
- }
-
- }
-
- });
-
-})();
diff --git a/media/system/js/fields/passwordview.min.js b/media/system/js/fields/passwordview.min.js
deleted file mode 100644
index 33b42bf4d60d6..0000000000000
--- a/media/system/js/fields/passwordview.min.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(){"use strict";document.addEventListener("DOMContentLoaded",function(){for(var e=document.getElementsByTagName("input"),t=0,a=e.length;t i; i++) {
+ if (this.hasOwnProperty(sets[i]) && this[sets[i]] > 0) {
+ mods = mods + 1;
+ }
+ }
+
+ score += this.calc(value, /[a-z]/g, this.lowercase, mods);
+ score += this.calc(value, /[A-Z]/g, this.uppercase, mods);
+ score += this.calc(value, /[0-9]/g, this.numbers, mods);
+ score += this.calc(value, /[\$\!\#\?\=\;\:\*\-\_\€\%\&\(\)\`\´]/g, this.special, mods);
+ if (mods == 1) {
+ score += value.length > this.length ? 100 : 100 / this.length * value.length;
+ } else {
+ score += value.length > this.length ? 100 / mods : 100 / mods / this.length * value.length;
+ }
+
+ return score;
+ }
+ }, {
+ key: 'calc',
+ value: function calc(value, pattern, length, mods) {
+ var count = value.match(pattern);
+ if (count && count.length > length && length != 0) {
+ return 100 / mods;
+ }
+ if (count && length > 0) {
+ return 100 / mods / length * count.length;
+ } else {
+ return 0;
+ }
+ }
+ }]);
+
+ return PasswordStrength;
+ }();
+
+ var JoomlaFieldPassword = function (_HTMLElement) {
+ _inherits(JoomlaFieldPassword, _HTMLElement);
+
+ _createClass(JoomlaFieldPassword, [{
+ key: 'minLength',
+ get: function get() {
+ return parseInt(this.getAttribute('min-length') || 0);
+ }
+ }, {
+ key: 'minIntegers',
+ get: function get() {
+ return parseInt(this.getAttribute('min-integers') || 0);
+ }
+ }, {
+ key: 'minSymbols',
+ get: function get() {
+ return parseInt(this.getAttribute('min-symbols') || 0);
+ }
+ }, {
+ key: 'minUppercase',
+ get: function get() {
+ return parseInt(this.getAttribute('min-uppercase') || 0);
+ }
+ }, {
+ key: 'minLowercase',
+ get: function get() {
+ return parseInt(this.getAttribute('min-lowercase') || 0);
+ }
+ }, {
+ key: 'reveal',
+ get: function get() {
+ return this.getAttribute('reveal') || false;
+ }
+ }, {
+ key: 'showText',
+ get: function get() {
+ return this.getAttribute('text-show') || 'Show';
+ }
+ }, {
+ key: 'hideText',
+ get: function get() {
+ return this.getAttribute('text-hide') || 'Hide';
+ }
+ }, {
+ key: 'completeText',
+ get: function get() {
+ return this.getAttribute('text-complete') || 'Password meets site\'s requirements';
+ }
+ }, {
+ key: 'incompleteText',
+ get: function get() {
+ return this.getAttribute('text-incomplete') || 'Password does not meet site\'s requirements';
+ }
+
+ // attributeChangedCallback(attr, oldValue, newValue) {}
+
+ }], [{
+ key: 'observedAttributes',
+ get: function get() {
+ return ['min-length', 'min-integers', 'min-symbols', 'min-uppercase', 'min-lowercase', 'reveal', 'text-show', 'text-hide', 'text-complete', 'text-incomplete'];
+ }
+ }]);
+
+ function JoomlaFieldPassword() {
+ _classCallCheck(this, JoomlaFieldPassword);
+
+ var _this = _possibleConstructorReturn(this, (JoomlaFieldPassword.__proto__ || Object.getPrototypeOf(JoomlaFieldPassword)).call(this));
+
+ if (!window.Joomla) {
+ throw new Error('Joomla API is not iniatiated!');
+ }
+
+ _this.input = _this.querySelector('input');
+
+ if (!_this.input) {
+ throw new Error('Joomla Password field requires an input element!');
+ }
+
+ _this.meterLabel = '';
+ _this.meter = '';
+ return _this;
+ }
+
+ _createClass(JoomlaFieldPassword, [{
+ key: 'connectedCallback',
+ value: function connectedCallback() {
+ if (this.reveal === 'true') {
+ var parent = document.createElement('div');
+ var parentSpan = document.createElement('span');
+ var firstSpan = document.createElement('span');
+ var secondSpan = document.createElement('span');
+
+ parent.classList.add('input-group-append');
+ parentSpan.setAttribute('class', 'input-group-text');
+ firstSpan.setAttribute('class', 'fa fa-eye');
+ firstSpan.setAttribute('aria-hidden', 'true');
+ secondSpan.setAttribute('class', 'sr-only');
+ secondSpan.innerText = this.showText;
+
+ parentSpan.appendChild(firstSpan);
+ parentSpan.appendChild(secondSpan);
+ parent.appendChild(parentSpan);
+
+ var groupInput = this.querySelector('.input-group');
+
+ if (!groupInput) {
+ groupInput = document.createElement('div');
+ groupInput.classList.add('input-group');
+
+ groupInput.appendChild(this.input);
+ this.appendChild(groupInput);
+ }
+
+ groupInput.appendChild(parent);
+
+ var that = this;
+
+ this.input = this.querySelector('input');
+
+ // @TODO Remove Font awesome dependency
+ // @TODO Remove Bootstrap dependency
+ firstSpan.addEventListener('click', function () {
+
+ if (firstSpan.classList.contains('fa-eye')) {
+ // Update the icon class
+ firstSpan.classList.remove('fa-eye');
+ firstSpan.classList.add('fa-eye-slash');
+
+ // Update the input type
+ that.input.type = 'text';
+
+ // Update the text for screenreaders
+ secondSpan.innerText = that.showText;
+ } else {
+ // Update the icon class
+ firstSpan.classList.add('fa-eye');
+ firstSpan.classList.remove('fa-eye-slash');
+
+ // Update the input type
+ that.input.type = 'password';
+
+ // Update the text for screenreaders
+ secondSpan.innerText = that.hideText;
+ }
+ });
+ }
+
+ // Meter is enabled
+ // @TODO Remove Bootstrap dependency
+ if (this.minLength && this.minLength > 0 || this.minIntegers && this.minIntegers > 0 || this.minSymbols && this.minSymbols > 0 || this.minUppercase && this.minUppercase > 0 || this.minLowercase && this.minLowercase > 0) {
+ var startClass = '';
+ var initialVal = '';
+ var el = void 0;
+
+ if (!this.input.value.length) {
+ startClass = ' bg-danger';
+ initialVal = 0;
+ }
+
+ var i = Math.random().toString(36).substr(2, 9);
+
+ /** Create a progress meter and the label **/
+ var meter = document.createElement('div');
+ meter.setAttribute('class', 'progress');
+
+ this.meter = document.createElement('div');
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated' + startClass);
+ this.meter.style.width = 0 + initialVal;
+ this.meter.max = 100;
+ this.meter.setAttribute('aria-describedby', 'password-' + i);
+ meter.appendChild(this.meter);
+
+ this.meterLabel = document.createElement('div');
+ this.meterLabel.setAttribute('class', 'text-xs-center');
+ this.meterLabel.setAttribute('id', 'password-' + i);
+
+ this.insertAdjacentElement('beforeend', this.meterLabel);
+ this.insertAdjacentElement('beforeend', meter);
+
+ /** Add a data attribute for the required **/
+ if (this.input.value.length > 0) {
+ this.input.setAttribute('required', '');
+ }
+
+ /** Add a listener for input data change **/
+ this.input.addEventListener('keyup', this.getMeter.bind(this));
+
+ // Set the validation handler
+ // @TODO refactor the validation.js to reflect the changes here!
+ this.setAttribute('validation-handler', 'password-strength' + '_' + Math.random().toString(36).substr(2, 9));
+
+ if (document.formvalidator) {
+ document.formvalidator.setHandler(this.getAttribute('validation-handler'), this.handler.bind(this));
+ }
+ }
+ }
+ }, {
+ key: 'disconnectedCallback',
+ value: function disconnectedCallback() {}
+
+ /** Method to check the input and set the meter **/
+
+ }, {
+ key: 'getMeter',
+ value: function getMeter() {
+
+ if (!this.meter || !this.meterLabel) {
+ return;
+ }
+
+ var strength = new PasswordStrength({
+ lowercase: this.minLowercase ? this.minLowercase : 0,
+ uppercase: this.minUppercase ? this.minUppercase : 0,
+ numbers: this.minIntegers ? this.minIntegers : 0,
+ special: this.minSymbols ? this.minSymbols : 0,
+ length: this.minLength ? this.minLength : 4
+ });
+
+ var score = strength.getScore(this.input.value);
+
+ if (score > 79) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.completeText;
+ }
+ if (score > 64 && score < 80) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score > 50 && score < 65) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score > 40 && score < 51) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score < 41) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-danger');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score === 100) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-success');
+ }
+ this.meter.style.width = score + '%';
+
+ if (!this.input.value.length) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated');
+ this.meterLabel.innerHTML = '';
+ this.input.setAttribute('required', '');
+ }
+ }
+ }, {
+ key: 'handler',
+ value: function handler(value) {
+ var strength = new PasswordStrength({
+ lowercase: this.minLowercase ? this.minLowercase : 0,
+ uppercase: this.minUppercase ? this.minUppercase : 0,
+ numbers: this.minIntegers ? this.minIntegers : 0,
+ special: this.minSymbols ? this.minSymbols : 0,
+ length: this.minLength ? this.minLength : 4
+ });
+
+ if (strength.getScore(value) === 100) {
+ return true;
+ }
+
+ return false;
+ }
+ }]);
+
+ return JoomlaFieldPassword;
+ }(HTMLElement);
+
+ customElements.define('joomla-field-password', JoomlaFieldPassword);
+})(customElements);
+
+},{}]},{},[1]);
diff --git a/media/system/webcomponents/js/joomla-field-password-es5.min.js b/media/system/webcomponents/js/joomla-field-password-es5.min.js
new file mode 100644
index 0000000000000..1b42f8f11cf7e
--- /dev/null
+++ b/media/system/webcomponents/js/joomla-field-password-es5.min.js
@@ -0,0 +1,4 @@
+(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;ie;e++)this.hasOwnProperty(d[e])&&0this.length?100:100/this.length*a.length:a.length>this.length?100/c:100/c/this.length*a.length,b}},{key:'calc',value:function calc(a,b,c,d){var e=a.match(b);return e&&e.length>c&&0!=c?100/d:e&&0c&&(this.meter.setAttribute('class','progress-bar progress-bar-striped progress-bar-animated bg-warning'),this.meterLabel.innerHTML=this.incompleteText),50c&&(this.meter.setAttribute('class','progress-bar progress-bar-striped progress-bar-animated bg-warning'),this.meterLabel.innerHTML=this.incompleteText),40c&&(this.meter.setAttribute('class','progress-bar progress-bar-striped progress-bar-animated bg-warning'),this.meterLabel.innerHTML=this.incompleteText),41>c&&(this.meter.setAttribute('class','progress-bar progress-bar-striped progress-bar-animated bg-danger'),this.meterLabel.innerHTML=this.incompleteText),100===c&&this.meter.setAttribute('class','progress-bar progress-bar-striped progress-bar-animated bg-success'),this.meter.style.width=c+'%',this.input.value.length||(this.meter.setAttribute('class','progress-bar progress-bar-striped progress-bar-animated'),this.meterLabel.innerHTML='',this.input.setAttribute('required',''))}}},{key:'handler',value:function handler(a){var c=new b({lowercase:this.minLowercase?this.minLowercase:0,uppercase:this.minUppercase?this.minUppercase:0,numbers:this.minIntegers?this.minIntegers:0,special:this.minSymbols?this.minSymbols:0,length:this.minLength?this.minLength:4});return 100===c.getScore(a)}}]),c}(HTMLElement);a.define('joomla-field-password',c)})(customElements);
+
+},{}]},{},[1]);
diff --git a/media/system/webcomponents/js/joomla-field-password.js b/media/system/webcomponents/js/joomla-field-password.js
new file mode 100644
index 0000000000000..6bf8dd4bc290e
--- /dev/null
+++ b/media/system/webcomponents/js/joomla-field-password.js
@@ -0,0 +1,277 @@
+;(function(customElements) {
+ "use strict";
+
+ /**
+ * PasswordStrength script by Thomas Kjaergaard
+ * License: MIT
+ * Repo: https://github.com/tkjaergaard/Password-Strength
+ */
+ class PasswordStrength {
+ constructor(settings) {
+ this.lowercase = settings.lowercase || 0;
+ this.uppercase = settings.uppercase || 0;
+ this.numbers = settings.numbers || 0;
+ this.special = settings.special || 0;
+ this.length = settings.length || 4;
+ }
+
+ getScore(value) {
+ var score = 0, mods = 0;
+ var sets = ['lowercase', 'uppercase', 'numbers', 'special', 'length'];
+ for (var i = 0, l = sets.length; l > i; i++) {
+ if (this.hasOwnProperty(sets[i]) && this[sets[i]] > 0) {
+ mods = mods + 1;
+ }
+ }
+
+ score += this.calc(value, /[a-z]/g, this.lowercase, mods);
+ score += this.calc(value, /[A-Z]/g, this.uppercase, mods);
+ score += this.calc(value, /[0-9]/g, this.numbers, mods);
+ score += this.calc(value, /[\$\!\#\?\=\;\:\*\-\_\€\%\&\(\)\`\´]/g, this.special, mods);
+ if (mods == 1) {
+ score += value.length > this.length ? 100 : 100 / this.length * value.length;
+ } else {
+ score += value.length > this.length ? (100 / mods) : (100 / mods) / this.length * value.length;
+ }
+
+ return score;
+ }
+
+ calc(value, pattern, length, mods) {
+ const count = value.match(pattern);
+ if (count && count.length > length && length != 0) {
+ return 100 / mods;
+ }
+ if (count && length > 0) {
+ return (100 / mods) / length * count.length;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ class JoomlaFieldPassword extends HTMLElement {
+ static get observedAttributes() {
+ return ['min-length', 'min-integers', 'min-symbols', 'min-uppercase', 'min-lowercase', 'reveal', 'text-show', 'text-hide', 'text-complete', 'text-incomplete'];
+ }
+
+ get minLength() { return parseInt(this.getAttribute('min-length') || 0); }
+ get minIntegers() { return parseInt(this.getAttribute('min-integers') || 0); }
+ get minSymbols() { return parseInt(this.getAttribute('min-symbols') || 0); }
+ get minUppercase() { return parseInt(this.getAttribute('min-uppercase') || 0); }
+ get minLowercase() { return parseInt(this.getAttribute('min-lowercase') || 0); }
+ get reveal() { return this.getAttribute('reveal') || false; }
+ get showText() { return this.getAttribute('text-show') || 'Show'; }
+ get hideText() { return this.getAttribute('text-hide') || 'Hide'; }
+ get completeText() { return this.getAttribute('text-complete') || 'Password meets site\'s requirements'; }
+ get incompleteText() { return this.getAttribute('text-incomplete') || 'Password does not meet site\'s requirements'; }
+
+ // attributeChangedCallback(attr, oldValue, newValue) {}
+
+ constructor() {
+ super();
+
+ if (!window.Joomla) {
+ throw new Error('Joomla API is not iniatiated!')
+ }
+
+ this.input = this.querySelector('input');
+
+ if (!this.input) {
+ throw new Error('Joomla Password field requires an input element!')
+ }
+
+ this.meterLabel = ''
+ this.meter = ''
+ }
+
+ connectedCallback() {
+ if (this.reveal === 'true') {
+ const parent = document.createElement('div');
+ const parentSpan = document.createElement('span');
+ const firstSpan = document.createElement('span');
+ const secondSpan = document.createElement('span');
+
+ parent.classList.add('input-group-append');
+ parentSpan.setAttribute('class', 'input-group-text');
+ firstSpan.setAttribute('class', 'fa fa-eye');
+ firstSpan.setAttribute('aria-hidden', 'true');
+ secondSpan.setAttribute('class', 'sr-only');
+ secondSpan.innerText = this.showText;
+
+ parentSpan.appendChild(firstSpan);
+ parentSpan.appendChild(secondSpan);
+ parent.appendChild(parentSpan);
+
+ let groupInput = this.querySelector('.input-group');
+
+ if (!groupInput) {
+ groupInput = document.createElement('div');
+ groupInput.classList.add('input-group');
+
+ groupInput.appendChild(this.input);
+ this.appendChild(groupInput);
+ }
+
+ groupInput.appendChild(parent);
+
+ const that = this;
+
+ this.input = this.querySelector('input');
+
+ // @TODO Remove Font awesome dependency
+ // @TODO Remove Bootstrap dependency
+ firstSpan.addEventListener('click', () => {
+
+ if (firstSpan.classList.contains('fa-eye')) {
+ // Update the icon class
+ firstSpan.classList.remove('fa-eye');
+ firstSpan.classList.add('fa-eye-slash');
+
+ // Update the input type
+ that.input.type = 'text';
+
+ // Update the text for screenreaders
+ secondSpan.innerText = that.showText;
+ } else {
+ // Update the icon class
+ firstSpan.classList.add('fa-eye');
+ firstSpan.classList.remove('fa-eye-slash');
+
+ // Update the input type
+ that.input.type = 'password';
+
+ // Update the text for screenreaders
+ secondSpan.innerText = that.hideText;
+ }
+ });
+ }
+
+ // Meter is enabled
+ // @TODO Remove Bootstrap dependency
+ if (this.minLength && this.minLength > 0
+ ||this.minIntegers && this.minIntegers > 0
+ ||this.minSymbols && this.minSymbols > 0
+ ||this.minUppercase && this.minUppercase > 0
+ ||this.minLowercase && this.minLowercase > 0
+ ) {
+ let startClass = '';
+ let initialVal = '';
+ let el;
+
+ if (!this.input.value.length) {
+ startClass = ' bg-danger';
+ initialVal = 0;
+ }
+
+ const i = Math.random().toString(36).substr(2, 9);
+
+ /** Create a progress meter and the label **/
+ const meter = document.createElement('div');
+ meter.setAttribute('class', 'progress');
+
+ this.meter = document.createElement('div');
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated' + startClass);
+ this.meter.style.width = 0 + initialVal;
+ this.meter.max = 100;
+ this.meter.setAttribute('aria-describedby', 'password-' + i);
+ meter.appendChild(this.meter);
+
+ this.meterLabel = document.createElement('div');
+ this.meterLabel.setAttribute('class', 'text-xs-center');
+ this.meterLabel.setAttribute('id', 'password-' + i);
+
+ this.insertAdjacentElement('beforeend', this.meterLabel);
+ this.insertAdjacentElement('beforeend', meter);
+
+ /** Add a data attribute for the required **/
+ if (this.input.value.length > 0) {
+ this.input.setAttribute('required', '');
+ }
+
+ /** Add a listener for input data change **/
+ this.input.addEventListener('keyup', this.getMeter.bind(this));
+
+ // Set the validation handler
+ // @TODO refactor the validation.js to reflect the changes here!
+ this.setAttribute('validation-handler', 'password-strength' + '_' + Math.random().toString(36).substr(2, 9));
+
+ if (document.formvalidator) {
+ document.formvalidator.setHandler(this.getAttribute('validation-handler'), this.handler.bind(this));
+ }
+ }
+ }
+
+ disconnectedCallback() {
+
+ }
+
+ /** Method to check the input and set the meter **/
+ getMeter() {
+
+ if (!this.meter || !this.meterLabel) {
+ return;
+ }
+
+ const strength = new PasswordStrength({
+ lowercase: this.minLowercase ? this.minLowercase : 0,
+ uppercase: this.minUppercase ? this.minUppercase : 0,
+ numbers : this.minIntegers ? this.minIntegers : 0,
+ special : this.minSymbols ? this.minSymbols : 0,
+ length : this.minLength ? this.minLength : 4
+ });
+
+ const score = strength.getScore(this.input.value);
+
+ if (score > 79) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.completeText;
+ }
+ if (score > 64 && score < 80) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score > 50 && score < 65) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score > 40 && score < 51) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-warning');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score < 41) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-danger');
+ this.meterLabel.innerHTML = this.incompleteText;
+ }
+ if (score === 100) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated bg-success');
+ }
+ this.meter.style.width = score + '%';
+
+ if (!this.input.value.length) {
+ this.meter.setAttribute('class', 'progress-bar progress-bar-striped progress-bar-animated');
+ this.meterLabel.innerHTML = '';
+ this.input.setAttribute('required', '');
+ }
+ }
+
+ handler(value) {
+ const strength = new PasswordStrength({
+ lowercase: this.minLowercase ? this.minLowercase : 0,
+ uppercase: this.minUppercase ? this.minUppercase : 0,
+ numbers : this.minIntegers ? this.minIntegers : 0,
+ special : this.minSymbols ? this.minSymbols : 0,
+ length : this.minLength ? this.minLength : 4
+ });
+
+ if (strength.getScore(value) === 100) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ customElements.define('joomla-field-password', JoomlaFieldPassword);
+
+})(customElements);
diff --git a/media/system/webcomponents/js/joomla-field-password.min.js b/media/system/webcomponents/js/joomla-field-password.min.js
new file mode 100644
index 0000000000000..1865adb999d7e
--- /dev/null
+++ b/media/system/webcomponents/js/joomla-field-password.min.js
@@ -0,0 +1 @@
+!function(e){"use strict";class t{constructor(e){this.lowercase=e.lowercase||0,this.uppercase=e.uppercase||0,this.numbers=e.numbers||0,this.special=e.special||0,this.length=e.length||4}getScore(e){for(var t=0,s=0,r=["lowercase","uppercase","numbers","special","length"],i=0,n=r.length;n>i;i++)this.hasOwnProperty(r[i])&&this[r[i]]>0&&(s+=1);return t+=this.calc(e,/[a-z]/g,this.lowercase,s),t+=this.calc(e,/[A-Z]/g,this.uppercase,s),t+=this.calc(e,/[0-9]/g,this.numbers,s),t+=this.calc(e,/[\$\!\#\?\=\;\:\*\-\_\€\%\&\(\)\`\´]/g,this.special,s),t+=1==s?e.length>this.length?100:100/this.length*e.length:e.length>this.length?100/s:100/s/this.length*e.length}calc(e,t,s,r){const i=e.match(t);return i&&i.length>s&&0!=s?100/r:i&&s>0?100/r/s*i.length:0}}e.define("joomla-field-password",class extends HTMLElement{static get observedAttributes(){return["min-length","min-integers","min-symbols","min-uppercase","min-lowercase","reveal","text-show","text-hide","text-complete","text-incomplete"]}get minLength(){return parseInt(this.getAttribute("min-length")||0)}get minIntegers(){return parseInt(this.getAttribute("min-integers")||0)}get minSymbols(){return parseInt(this.getAttribute("min-symbols")||0)}get minUppercase(){return parseInt(this.getAttribute("min-uppercase")||0)}get minLowercase(){return parseInt(this.getAttribute("min-lowercase")||0)}get reveal(){return this.getAttribute("reveal")||!1}get showText(){return this.getAttribute("text-show")||"Show"}get hideText(){return this.getAttribute("text-hide")||"Hide"}get completeText(){return this.getAttribute("text-complete")||"Password meets site's requirements"}get incompleteText(){return this.getAttribute("text-incomplete")||"Password does not meet site's requirements"}constructor(){if(super(),!window.Joomla)throw new Error("Joomla API is not iniatiated!");if(this.input=this.querySelector("input"),!this.input)throw new Error("Joomla Password field requires an input element!");this.meterLabel="",this.meter=""}connectedCallback(){if("true"===this.reveal){const e=document.createElement("div"),t=document.createElement("span"),s=document.createElement("span"),r=document.createElement("span");e.classList.add("input-group-append"),t.setAttribute("class","input-group-text"),s.setAttribute("class","fa fa-eye"),s.setAttribute("aria-hidden","true"),r.setAttribute("class","sr-only"),r.innerText=this.showText,t.appendChild(s),t.appendChild(r),e.appendChild(t);let i=this.querySelector(".input-group");i||((i=document.createElement("div")).classList.add("input-group"),i.appendChild(this.input),this.appendChild(i)),i.appendChild(e);const n=this;this.input=this.querySelector("input"),s.addEventListener("click",()=>{s.classList.contains("fa-eye")?(s.classList.remove("fa-eye"),s.classList.add("fa-eye-slash"),n.input.type="text",r.innerText=n.showText):(s.classList.add("fa-eye"),s.classList.remove("fa-eye-slash"),n.input.type="password",r.innerText=n.hideText)})}if(this.minLength&&this.minLength>0||this.minIntegers&&this.minIntegers>0||this.minSymbols&&this.minSymbols>0||this.minUppercase&&this.minUppercase>0||this.minLowercase&&this.minLowercase>0){let e="",t="";this.input.value.length||(e=" bg-danger",t=0);const s=Math.random().toString(36).substr(2,9),r=document.createElement("div");r.setAttribute("class","progress"),this.meter=document.createElement("div"),this.meter.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated"+e),this.meter.style.width=0+t,this.meter.max=100,this.meter.setAttribute("aria-describedby","password-"+s),r.appendChild(this.meter),this.meterLabel=document.createElement("div"),this.meterLabel.setAttribute("class","text-xs-center"),this.meterLabel.setAttribute("id","password-"+s),this.insertAdjacentElement("beforeend",this.meterLabel),this.insertAdjacentElement("beforeend",r),this.input.value.length>0&&this.input.setAttribute("required",""),this.input.addEventListener("keyup",this.getMeter.bind(this)),this.setAttribute("validation-handler","password-strength_"+Math.random().toString(36).substr(2,9)),document.formvalidator&&document.formvalidator.setHandler(this.getAttribute("validation-handler"),this.handler.bind(this))}}disconnectedCallback(){}getMeter(){if(!this.meter||!this.meterLabel)return;const e=new t({lowercase:this.minLowercase?this.minLowercase:0,uppercase:this.minUppercase?this.minUppercase:0,numbers:this.minIntegers?this.minIntegers:0,special:this.minSymbols?this.minSymbols:0,length:this.minLength?this.minLength:4}).getScore(this.input.value);e>79&&(this.meter.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-warning"),this.meterLabel.innerHTML=this.completeText),e>64&&e<80&&(this.meter.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-warning"),this.meterLabel.innerHTML=this.incompleteText),e>50&&e<65&&(this.meter.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-warning"),this.meterLabel.innerHTML=this.incompleteText),e>40&&e<51&&(this.meter.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-warning"),this.meterLabel.innerHTML=this.incompleteText),e<41&&(this.meter.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-danger"),this.meterLabel.innerHTML=this.incompleteText),100===e&&this.meter.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated bg-success"),this.meter.style.width=e+"%",this.input.value.length||(this.meter.setAttribute("class","progress-bar progress-bar-striped progress-bar-animated"),this.meterLabel.innerHTML="",this.input.setAttribute("required",""))}handler(e){return 100===new t({lowercase:this.minLowercase?this.minLowercase:0,uppercase:this.minUppercase?this.minUppercase:0,numbers:this.minIntegers?this.minIntegers:0,special:this.minSymbols?this.minSymbols:0,length:this.minLength?this.minLength:4}).getScore(e)}})}(customElements);
\ No newline at end of file