PageSourceSearch

https://www.trendsday.be/a/en/userinterface/uibase/components/form…buic-fe-password-checker.js?rev=312T3ZEUe40

js trendsday.be collected 2026-09-29 16:05:49 UTC 9,477 bytes, 229 lines download raw bytes

1/**
2 * @requires	Prototype.js
3 * @param		A string with the input field ID
4 * @return		Public API, init() which initializes the password-strength component
5 * @description	PasswordStrength component to check the strength and valid passwords entered by the user.
6 */
7
8
9window.PbLib = window.PbLib || {};
10PbLib.UI = PbLib.UI || {};
11
12PbLib.UI.formElementPasswordChecker = function (domId, showStrength) {
13    this.changeDelay = false;
14
15    // Make sure to behave as a constructor function
16    if (PbLib.UI === this) {
17        return new PbLib.UI.formElementPasswordChecker(domId, showStrength);
18    }
19
20    this.showStrength = !!showStrength;
21
22    // Collect al the password strenth checker elments
23    this.passwordField = document.getElementById(domId);
24    this.checkboxElem = document.getElementById(domId + '-psc-checkbox');
25    this.checkboxElem.parentElement.removeAttribute('hidden');
26
27    document.addEventListener('click', this.handleOnClick.bind(this));
28
29    if (!showStrength) {
30        return;
31    }
32
33    var passwordFieldWidth = this.passwordField.offsetWidth;
34    this.passwordStrengthElem = document.createElement('span');
35    this.passwordStrengthElem.classList.add('psc-pi-strength');
36    this.passwordField.parentElement.insertBefore(this.passwordStrengthElem, this.passwordField);
37    this.passwordStrengthElem.appendChild(this.passwordField);
38
39    this.passwordStrengthContainerElem = this.passwordStrengthElem.parentElement.parentElement;
40    this.confirmPasswordField = this.passwordStrengthContainerElem.querySelector('.psc-password-repeat input');
41
42    this.passwordField.style.width = passwordFieldWidth + 'px';
43
44    // Add an element to show the strength text, weak, mediocre, strong, very strong.
45    if (!this.passwordStrengthTextElem) {
46        this.passwordStrengthTextElem = document.createElement('span');
47        this.passwordStrengthTextElem.classList.add('psc-ps-text');
48        this.passwordField.parentElement.appendChild(this.passwordStrengthTextElem);
49    }
50
51    // Set the observers on the input element and the document for handeling keystrokes and click.
52    this.passwordField.addEventListener('keyup', this.handleOnChange.bind(this));
53    this.passwordField.addEventListener('change', this.handleOnChange.bind(this));
54
55    if (this.confirmPasswordField) {
56        this.confirmPasswordField.style.width = passwordFieldWidth + 'px';
57        this.confirmPasswordField.addEventListener('keyup', this.handleOnChange.bind(this));
58        this.confirmPasswordField.addEventListener('change', this.handleOnChange.bind(this));
59    }
60};
61
62PbLib.UI.formElementPasswordChecker.prototype.getEntropy = function (password) {
63    if (!PbLib.UI.hasOwnProperty('entropyData')) {
64        PbLib.UI.entropyData = {
65            'sets': [
66                ['0'.charCodeAt(0), '9'.charCodeAt(0)],
67                ['A'.charCodeAt(0), 'Z'.charCodeAt(0)],
68                ['a'.charCodeAt(0), 'z'.charCodeAt(0)],
69            ],
70        };
71        PbLib.UI.entropyData.lastSet = PbLib.UI.entropyData.sets.length;
72        let lastCharCode = PbLib.UI.entropyData.sets.at(-1)[1];
73        PbLib.UI.entropyData.sets.push([lastCharCode + 1, lastCharCode + 1]);
74    }
75
76    const pLen = password.length;
77    if (pLen <= 0) {
78        return 0;
79    }
80
81    const usedRanges = {};
82    for (let i = 0; i < pLen; i++) {
83        let charCode = password.charCodeAt(i);
84        for (let s = 0; s <= PbLib.UI.entropyData.lastSet; s++) {
85            if (charCode <= PbLib.UI.entropyData.sets[s][1] || s === PbLib.UI.entropyData.lastSet) {
86                if (!usedRanges.hasOwnProperty(s)) {
87                    usedRanges[s] = [charCode, charCode];
88                } else {
89                    usedRanges[s][0] = Math.min(usedRanges[s][0], charCode);
90                    usedRanges[s][1] = Math.max(usedRanges[s][1], charCode);
91                }
92                break;
93            }
94        }
95    }
96    const totalPasswordSpace = Object.keys(usedRanges).reduce(
97        (sum, key) => sum + usedRanges[key][1] - usedRanges[key][0] + 1,
98        0
99    );
100    return Math.floor(pLen * Math.log(totalPasswordSpace) / Math.log(2));
101};
102
103PbLib.UI.formElementPasswordChecker.prototype.handleOnChange = function (event) {
104
105    var element = event.target;
106    var pw = this.passwordField.value;
107    var ent;
108
109    // Get the password strength
110    if (pw) {
111        ent = this.getEntropy(pw);
112    }
113
114    // Set the correct class and text according to the password strength score.
115    if (!pw && (element === this.passwordField || element === this.confirmPasswordField)) {
116        this.passwordStrengthElem.className = 'psc-pi-strength';
117    } else if (ent < 40) {
118        this.passwordStrengthTextElem.innerHTML = 'Weak';
119        this.passwordStrengthElem.className = 'psc-pi-strength psc-password-strength-weak';
120    } else if (ent < 49) {
121        this.passwordStrengthTextElem.innerHTML = 'Fair';
122        this.passwordStrengthElem.className = 'psc-pi-strength psc-password-strength-fair';
123    } else if (ent < 65) {
124        this.passwordStrengthTextElem.innerHTML = 'Strong';
125        this.passwordStrengthElem.className = 'psc-pi-strength psc-password-strength-strong';
126    } else {
127        this.passwordStrengthTextElem.innerHTML = 'Very strong';
128        this.passwordStrengthElem.className = 'psc-pi-strength psc-password-strength-verystrong';
129    }
130
131    // Trigger password validator on input field changes.
132    if (this.confirmPasswordField &&
133        (element === this.passwordField || element === this.confirmPasswordField)
134    ) {
135        if (this.changeDelay) {
136            window.clearTimeout(this.changeDelay);
137            this.changeDelay = false;
138        }
139
140        var boundMatchPasswords = (function () {
141            this.matchPasswords();
142        }).bind(this);
143
144        this.changeDelay = setTimeout(function () {
145            boundMatchPasswords();
146        }, 1000);
147    }
148};
149
150PbLib.UI.formElementPasswordChecker.prototype.toggleInputType = function () {
151    // Change the password input type to text or password
152    var inputType = this.checkboxElem.checked === true ? 'text' : 'password';
153
154    this.passwordField.setAttribute('type', inputType);
155    if (this.confirmPasswordField) {
156        this.confirmPasswordField.setAttribute('type', inputType);
157    }
158};
159
160PbLib.UI.formElementPasswordChecker.prototype.handleOnClick = function (event) {
161    var element = event.target;
162
163    if (this.showStrength) {
164        // Check if the element equals one of the password textfields.
165        if (element === this.passwordStrengthElem || element === this.passwordStrengthTextElem) {
166            if (!this.passwordStrengBubble) {
167                // Load the Bubble CSS file when needed.
168                PbLib.loadCss(
169                    PbLib.getNewURI('ui/uibase/components/content-bubble/pbuic-content-bubble.css'),
170                    this.toggleBubble.bind(this)
171                );
172            } else if (this.passwordStrengBubble.style.display === 'none') {
173                // If Bubble already exists and is hidden, show it.
174                this.passwordStrengBubble.style.removeProperty('display');
175            } else {
176                this.passwordStrengBubble.style.display = 'none';
177            }
178        } else if (this.passwordStrengBubble) {
179            this.passwordStrengBubble.style.display = 'none';
180        }
181    }
182
183    // Check if checkbox is changed to change the input type of the password field.
184    if (element === this.checkboxElem) {
185        this.toggleInputType();
186    }
187};
188
189PbLib.UI.formElementPasswordChecker.prototype.toggleBubble = function () {
190    if (!this.passwordStrengBubble) {
191        // Add new bubble to the DOM.
192        this.passwordStrengBubble = document.createElement('span');
193        this.passwordStrengBubble.classList.add('pbuic-content-bubble');
194        this.passwordStrengBubble.innerHTML =
195            '<p>' +
196            'A longer password containing different characters (@#$, a-z, A-Z, and 0-9) is stronger.' +
197            '</p><span class="pbuic-cb-arrow"></span>';
198        this.passwordStrengBubble.style.top = this.passwordStrengthElem.offsetHeight + 10 + 'px';
199        this.passwordStrengthElem.appendChild(this.passwordStrengBubble);
200    } else {
201        this.passwordStrengBubble.style.removeProperty('display');
202    }
203};
204
205PbLib.UI.formElementPasswordChecker.prototype.matchPasswords = function () {
206    var pwOrigin = this.passwordField.value;
207    var pwMatch = this.confirmPasswordField.value;
208
209    // Add an extra class to the container element when passwords do not match.
210    if ((pwOrigin.length > 0 && pwMatch.length > 0) && (pwOrigin !== pwMatch)) {
211        this.passwordField.parentElement.parentElement.classList.add('psc-invalid');
212
213        if (!this.passwordNoMatch) {
214            // Creat an element for the password do not match text.
215            this.passwordNoMatch = document.createElement('span');
216            this.passwordNoMatch.classList.add('pbuic-pr-no-match');
217            this.passwordNoMatch.innerHTML = 'The passwords don\'t match.';
218            this.confirmPasswordField.parentElement.appendChild(this.passwordNoMatch);
219        } else {
220            this.passwordNoMatch.style.removeProperty('display');
221        }
222
223    } else if (pwOrigin === pwMatch || (pwOrigin.length === 0 || pwMatch.length === 0)) {
224        this.passwordField.parentElement.parentElement.classList.remove('psc-invalid');
225        if (this.passwordNoMatch) {
226            this.passwordNoMatch.style.display = 'none';
227        }
228    }
229};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.