1 | import { Directive, ElementRef, NgZone, Input, HostListener, NgModule } from '@angular/core';
|
2 | import { CommonModule } from '@angular/common';
|
3 | import { DomHandler, ConnectedOverlayScrollHandler } from 'primeng/dom';
|
4 |
|
5 | class Password {
|
6 | constructor(el, zone) {
|
7 | this.el = el;
|
8 | this.zone = zone;
|
9 | this.promptLabel = 'Enter a password';
|
10 | this.weakLabel = 'Weak';
|
11 | this.mediumLabel = 'Medium';
|
12 | this.strongLabel = 'Strong';
|
13 | this.feedback = true;
|
14 | }
|
15 | set showPassword(show) {
|
16 | this.el.nativeElement.type = show ? 'text' : 'password';
|
17 | }
|
18 | ngDoCheck() {
|
19 | this.updateFilledState();
|
20 | }
|
21 | onInput(e) {
|
22 | this.updateFilledState();
|
23 | }
|
24 | updateFilledState() {
|
25 | this.filled = this.el.nativeElement.value && this.el.nativeElement.value.length;
|
26 | }
|
27 | createPanel() {
|
28 | this.panel = document.createElement('div');
|
29 | this.panel.className = 'p-password-panel p-component p-password-panel-overlay p-connected-overlay';
|
30 | this.meter = document.createElement('div');
|
31 | this.meter.className = 'p-password-meter';
|
32 | this.info = document.createElement('div');
|
33 | this.info.className = 'p-password-info';
|
34 | this.info.textContent = this.promptLabel;
|
35 | this.panel.appendChild(this.meter);
|
36 | this.panel.appendChild(this.info);
|
37 | this.panel.style.minWidth = DomHandler.getOuterWidth(this.el.nativeElement) + 'px';
|
38 | document.body.appendChild(this.panel);
|
39 | }
|
40 | showOverlay() {
|
41 | if (this.feedback) {
|
42 | if (!this.panel) {
|
43 | this.createPanel();
|
44 | }
|
45 | this.panel.style.zIndex = String(++DomHandler.zindex);
|
46 | this.panel.style.display = 'block';
|
47 | this.zone.runOutsideAngular(() => {
|
48 | setTimeout(() => {
|
49 | DomHandler.addClass(this.panel, 'p-connected-overlay-visible');
|
50 | this.bindScrollListener();
|
51 | this.bindDocumentResizeListener();
|
52 | }, 1);
|
53 | });
|
54 | DomHandler.absolutePosition(this.panel, this.el.nativeElement);
|
55 | }
|
56 | }
|
57 | hideOverlay() {
|
58 | if (this.feedback && this.panel) {
|
59 | DomHandler.addClass(this.panel, 'p-connected-overlay-hidden');
|
60 | DomHandler.removeClass(this.panel, 'p-connected-overlay-visible');
|
61 | this.unbindScrollListener();
|
62 | this.unbindDocumentResizeListener();
|
63 | this.zone.runOutsideAngular(() => {
|
64 | setTimeout(() => {
|
65 | this.ngOnDestroy();
|
66 | }, 150);
|
67 | });
|
68 | }
|
69 | }
|
70 | onFocus() {
|
71 | this.showOverlay();
|
72 | }
|
73 | onBlur() {
|
74 | this.hideOverlay();
|
75 | }
|
76 | onKeyup(e) {
|
77 | if (this.feedback) {
|
78 | let value = e.target.value, label = null, meterPos = null;
|
79 | if (value.length === 0) {
|
80 | label = this.promptLabel;
|
81 | meterPos = '0px 0px';
|
82 | }
|
83 | else {
|
84 | var score = this.testStrength(value);
|
85 | if (score < 30) {
|
86 | label = this.weakLabel;
|
87 | meterPos = '0px -10px';
|
88 | }
|
89 | else if (score >= 30 && score < 80) {
|
90 | label = this.mediumLabel;
|
91 | meterPos = '0px -20px';
|
92 | }
|
93 | else if (score >= 80) {
|
94 | label = this.strongLabel;
|
95 | meterPos = '0px -30px';
|
96 | }
|
97 | }
|
98 | if (!this.panel || !DomHandler.hasClass(this.panel, 'p-connected-overlay-visible')) {
|
99 | this.showOverlay();
|
100 | }
|
101 | this.meter.style.backgroundPosition = meterPos;
|
102 | this.info.textContent = label;
|
103 | }
|
104 | }
|
105 | testStrength(str) {
|
106 | let grade = 0;
|
107 | let val;
|
108 | val = str.match('[0-9]');
|
109 | grade += this.normalize(val ? val.length : 1 / 4, 1) * 25;
|
110 | val = str.match('[a-zA-Z]');
|
111 | grade += this.normalize(val ? val.length : 1 / 2, 3) * 10;
|
112 | val = str.match('[!@#$%^&*?_~.,;=]');
|
113 | grade += this.normalize(val ? val.length : 1 / 6, 1) * 35;
|
114 | val = str.match('[A-Z]');
|
115 | grade += this.normalize(val ? val.length : 1 / 6, 1) * 30;
|
116 | grade *= str.length / 8;
|
117 | return grade > 100 ? 100 : grade;
|
118 | }
|
119 | normalize(x, y) {
|
120 | let diff = x - y;
|
121 | if (diff <= 0)
|
122 | return x / y;
|
123 | else
|
124 | return 1 + 0.5 * (x / (x + y / 4));
|
125 | }
|
126 | get disabled() {
|
127 | return this.el.nativeElement.disabled;
|
128 | }
|
129 | bindScrollListener() {
|
130 | if (!this.scrollHandler) {
|
131 | this.scrollHandler = new ConnectedOverlayScrollHandler(this.el.nativeElement, () => {
|
132 | if (DomHandler.hasClass(this.panel, 'p-connected-overlay-visible')) {
|
133 | this.hideOverlay();
|
134 | }
|
135 | });
|
136 | }
|
137 | this.scrollHandler.bindScrollListener();
|
138 | }
|
139 | unbindScrollListener() {
|
140 | if (this.scrollHandler) {
|
141 | this.scrollHandler.unbindScrollListener();
|
142 | }
|
143 | }
|
144 | bindDocumentResizeListener() {
|
145 | this.documentResizeListener = this.onWindowResize.bind(this);
|
146 | window.addEventListener('resize', this.documentResizeListener);
|
147 | }
|
148 | unbindDocumentResizeListener() {
|
149 | if (this.documentResizeListener) {
|
150 | window.removeEventListener('resize', this.documentResizeListener);
|
151 | this.documentResizeListener = null;
|
152 | }
|
153 | }
|
154 | onWindowResize() {
|
155 | this.hideOverlay();
|
156 | }
|
157 | ngOnDestroy() {
|
158 | if (this.panel) {
|
159 | if (this.scrollHandler) {
|
160 | this.scrollHandler.destroy();
|
161 | this.scrollHandler = null;
|
162 | }
|
163 | this.unbindDocumentResizeListener();
|
164 | document.body.removeChild(this.panel);
|
165 | this.panel = null;
|
166 | this.meter = null;
|
167 | this.info = null;
|
168 | }
|
169 | }
|
170 | }
|
171 | Password.decorators = [
|
172 | { type: Directive, args: [{
|
173 | selector: '[pPassword]',
|
174 | host: {
|
175 | '[class.p-inputtext]': 'true',
|
176 | '[class.p-component]': 'true',
|
177 | '[class.p-filled]': 'filled'
|
178 | }
|
179 | },] }
|
180 | ];
|
181 | Password.ctorParameters = () => [
|
182 | { type: ElementRef },
|
183 | { type: NgZone }
|
184 | ];
|
185 | Password.propDecorators = {
|
186 | promptLabel: [{ type: Input }],
|
187 | weakLabel: [{ type: Input }],
|
188 | mediumLabel: [{ type: Input }],
|
189 | strongLabel: [{ type: Input }],
|
190 | feedback: [{ type: Input }],
|
191 | showPassword: [{ type: Input }],
|
192 | onInput: [{ type: HostListener, args: ['input', ['$event'],] }],
|
193 | onFocus: [{ type: HostListener, args: ['focus',] }],
|
194 | onBlur: [{ type: HostListener, args: ['blur',] }],
|
195 | onKeyup: [{ type: HostListener, args: ['keyup', ['$event'],] }]
|
196 | };
|
197 | class PasswordModule {
|
198 | }
|
199 | PasswordModule.decorators = [
|
200 | { type: NgModule, args: [{
|
201 | imports: [CommonModule],
|
202 | exports: [Password],
|
203 | declarations: [Password]
|
204 | },] }
|
205 | ];
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 | export { Password, PasswordModule };
|
212 |
|