Implemented PasswordStrength Component
parent
e128009632
commit
d26626a969
|
@ -14,6 +14,7 @@
|
|||
<router-link to="/inputswitch">● InputSwitch</router-link>
|
||||
<router-link to="/inputtext">● InputText</router-link>
|
||||
<router-link to="/listbox">● Listbox</router-link>
|
||||
<router-link to="/password">● Password</router-link>
|
||||
<router-link to="/radiobutton">● RadioButton</router-link>
|
||||
<router-link to="/rating">● Rating</router-link>
|
||||
<router-link to="/selectbutton">● SelectButton</router-link>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
@import '../../components/inputswitch/InputSwitch.css';
|
||||
@import '../../components/listbox/Listbox.css';
|
||||
@import '../../components/panel/Panel.css';
|
||||
@import '../../components/password/Password.css';
|
||||
@import '../../components/progressbar/ProgressBar.css';
|
||||
@import '../../components/radiobutton/RadioButton.css';
|
||||
@import '../../components/rating/Rating.css';
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
.p-password-panel {
|
||||
padding: .25em .5em;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.p-password-panel .p-password-meter {
|
||||
height: 10px;
|
||||
background:transparent url("./images/password-meter.png") no-repeat left top;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.p-password-info {
|
||||
margin-top: .25em;
|
||||
}
|
||||
|
||||
.p-password-panel-overlay {
|
||||
position: absolute;
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
<template>
|
||||
<input ref="input" type="password" :class="['p-inputtext p-component', {'p-filled': filled}]" v-on="listeners" :value="value" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: String,
|
||||
promptLabel: {
|
||||
type: String,
|
||||
default: 'Enter a password'
|
||||
},
|
||||
weakLabel: {
|
||||
type: String,
|
||||
default: 'Weak'
|
||||
},
|
||||
mediumLabel: {
|
||||
type: String,
|
||||
default: 'Medium'
|
||||
},
|
||||
strongLabel: {
|
||||
type: String,
|
||||
default: 'Strong'
|
||||
},
|
||||
feedback: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
panel: null,
|
||||
meter: null,
|
||||
info: null,
|
||||
methods: {
|
||||
testStrength(str) {
|
||||
let grade = 0;
|
||||
let val;
|
||||
|
||||
val = str.match('[0-9]');
|
||||
grade += this.normalize(val ? val.length : 1/4, 1) * 25;
|
||||
|
||||
val = str.match('[a-zA-Z]');
|
||||
grade += this.normalize(val ? val.length : 1/2, 3) * 10;
|
||||
|
||||
val = str.match('[!@#$%^&*?_~.,;=]');
|
||||
grade += this.normalize(val ? val.length : 1/6, 1) * 35;
|
||||
|
||||
val = str.match('[A-Z]');
|
||||
grade += this.normalize(val ? val.length : 1/6, 1) * 30;
|
||||
|
||||
grade *= str.length / 8;
|
||||
|
||||
return grade > 100 ? 100 : grade;
|
||||
},
|
||||
normalize(x, y) {
|
||||
let diff = x - y;
|
||||
|
||||
if(diff <= 0)
|
||||
return x / y;
|
||||
else
|
||||
return 1 + 0.5 * (x / (x + y/4));
|
||||
},
|
||||
createPanel() {
|
||||
this.panel = document.createElement('div');
|
||||
this.panel.className = 'p-password-panel p-component p-hidden p-password-panel-overlay p-input-overlay';
|
||||
this.meter = document.createElement('div');
|
||||
this.meter.className = 'p-password-meter';
|
||||
this.info = document.createElement('div');
|
||||
this.info.className = 'p-password-info';
|
||||
this.info.textContent = this.promptLabel;
|
||||
|
||||
this.panel.style.minWidth = DomHandler.getOuterWidth(this.$refs.input) + 'px';
|
||||
this.panel.appendChild(this.meter);
|
||||
this.panel.appendChild(this.info);
|
||||
document.body.appendChild(this.panel);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
listeners() {
|
||||
return {
|
||||
...this.$listeners,
|
||||
input: event => this.$emit('input', event.target.value),
|
||||
focus: event => {
|
||||
if (this.feedback) {
|
||||
if (!this.panel) {
|
||||
this.createPanel();
|
||||
}
|
||||
|
||||
this.panel.style.zIndex = String(DomHandler.generateZIndex());
|
||||
this.panel.style.display = 'block';
|
||||
setTimeout(() => {
|
||||
DomHandler.addClass(this.panel, 'p-input-overlay-visible');
|
||||
DomHandler.removeClass(this.panel, 'p-input-overlay-hidden');
|
||||
}, 1);
|
||||
DomHandler.absolutePosition(this.panel, this.$refs.input);
|
||||
}
|
||||
|
||||
this.$emit('focus', event);
|
||||
},
|
||||
blur: event => {
|
||||
if (this.panel) {
|
||||
DomHandler.addClass(this.panel, 'p-input-overlay-hidden');
|
||||
DomHandler.removeClass(this.panel, 'p-input-overlay-visible');
|
||||
|
||||
setTimeout(() => {
|
||||
this.panel.style.display = 'none';
|
||||
DomHandler.removeClass(this.panel, 'p-input-overlay-hidden');
|
||||
}, 150);
|
||||
}
|
||||
|
||||
this.$emit('blur', event);
|
||||
},
|
||||
keyup: event => {
|
||||
if(this.panel) {
|
||||
let value = event.target.value;
|
||||
let label = null;
|
||||
let meterPos = null;
|
||||
|
||||
if (value.length === 0) {
|
||||
label = this.promptLabel;
|
||||
meterPos = '0px 0px';
|
||||
}
|
||||
else {
|
||||
let score = this.testStrength(value);
|
||||
|
||||
if (score < 30) {
|
||||
label = this.weakLabel;
|
||||
meterPos = '0px -10px';
|
||||
}
|
||||
else if (score >= 30 && score < 80) {
|
||||
label = this.mediumLabel;
|
||||
meterPos = '0px -20px';
|
||||
}
|
||||
else if (score >= 80) {
|
||||
label = this.strongLabel;
|
||||
meterPos = '0px -30px';
|
||||
}
|
||||
}
|
||||
|
||||
this.meter.style.backgroundPosition = meterPos;
|
||||
this.info.textContent = label;
|
||||
}
|
||||
|
||||
this.$emit('keyup', event);
|
||||
}
|
||||
};
|
||||
},
|
||||
filled() {
|
||||
return (this.value != null && this.value.toString().length > 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
Binary file not shown.
After Width: | Height: | Size: 118 B |
|
@ -13,6 +13,7 @@ import InputText from './components/inputtext/InputText';
|
|||
import Fieldset from './components/fieldset/Fieldset';
|
||||
import Listbox from './components/listbox/Listbox';
|
||||
import Panel from './components/panel/Panel';
|
||||
import Password from './components/password/Password';
|
||||
import ProgressBar from './components/progressbar/ProgressBar';
|
||||
import Rating from './components/rating/Rating';
|
||||
import RadioButton from './components/radiobutton/RadioButton';
|
||||
|
@ -44,6 +45,7 @@ Vue.component('p-inputtext', InputText);
|
|||
Vue.component('p-listbox', Listbox);
|
||||
Vue.component('p-fieldset', Fieldset);
|
||||
Vue.component('p-panel', Panel);
|
||||
Vue.component('p-password', Password);
|
||||
Vue.component('p-progressBar', ProgressBar);
|
||||
Vue.component('p-radioButton', RadioButton);
|
||||
Vue.component('p-rating', Rating);
|
||||
|
|
|
@ -71,6 +71,11 @@ export default new Router({
|
|||
name: 'panel',
|
||||
component: () => import('./views/panel/PanelDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/password',
|
||||
name: 'password',
|
||||
component: () => import('./views/password/PasswordDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/progressbar',
|
||||
name: 'progressbar',
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="content-section introduction">
|
||||
<div class="feature-intro">
|
||||
<h1>Password</h1>
|
||||
<p>Password displays strength indicator for password fields.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-section implementation">
|
||||
<p-password v-model="value" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
Loading…
Reference in New Issue