I would like to share my latest fancy password generator with you.
It will look like this:
Generated password field is also very simple;
<q-input
readonly
stack-label
type="text"
autocomplete="off"
v-model="generatedPassword"
label="Generated password"
>
<template v-slot:after>
<q-btn round flat dense icon="mdi-clipboard-arrow-up-outline" @click="copyGeneratedPassword" />
</template>
</q-input>
How the copy to clipboard button works
copyGeneratedPassword method is like this:
import { copyToClipboard } from 'quasar'
...
data: {
newPassword: ''
},
methods: {
copyGeneratedPassword () {
this.newPassword = this.generatedPassword
copyToClipboard(this.generatedPassword)
this.$q.notify({
progress: true,
type: 'positive',
message: `Generated password has been copied to clipboard.`
})
}
}
This method basically copies generatedPassword to clipboard as well as on to the newPassword (generatedPassword here is a computed property and described below).
this.$q.notify is another Quasar plugin
Notification plugin
Also the copyToClipboard helper comes from Quasar utils. I like using Quasar so much.
Now it’s time for the slider:
<q-item>
<q-item-section>
<q-slider
snap
label
markers
:step="12"
:min="0"
:max="48"
:color="strengthColor"
:label-value="strengthLabel"
v-model="strengthLevel"
/>
</q-item-section>
<q-item-section avatar>
<loading-progress
:progress="strengthLevel / 100"
shape="M23,3.1c-3.1-1.6-5.8-2.3-9.1-2.3c-3.2,0-6.3,0.8-9.1,2.3 M27.1,11c-1.5-2.1-3.3-3.7-5.5-4.8 c-4.7-2.4-10.7-2.4-15.3,0C4,7.4,2.2,9,0.7,11 M22.2,18.7c0-4.3-3.7-7.8-8.2-7.8s-8.2,3.5-8.2,7.8c0,2.5,0.6,4.9,1.6,6.8 c1.1,2.1,1.9,2.9,3.3,4.3 M22.6,27.4c-1.9,0-3.7-0.5-5.1-1.5c-2.4-1.6-3.9-4.3-3.9-7.2 M18.5,30.8c-2.6-0.8-4.3-1.7-6.1-3.5 c-2.3-2.3-3.5-5.3-3.5-8.5c0-2.6,2.3-4.8,5-4.8s5,2.2,5,4.8c0,1.7,1.5,3.2,3.4,3.2c1.9,0,3.4-1.4,3.4-3.2c0-6.1-5.3-11.1-11.8-11.1 c-4.6,0-8.9,2.6-10.8,6.6c-0.6,1.3-1,2.9-1,4.6c0,1.3,0.1,3.3,1.1,5.9"
fill-duration="2"
height="32"
width="30"
size="32"
/>
</q-item-section>
</q-item>
While the client slides right or left, strengthLevel changes from 0 to 48 ( I will explain why 48 is the maximum number here later). strengthColor and strengthLabel are computed properties are bound to strengthLevel.
LoadingProgress component here is actually Akryum/vue-progress-path with my custom fingerprint SVG. It’s not originally made for this purpose here but combination with QSlider works well, and also explains why I used 48 for the maximum value of QSlider. The length of the SVG determines the maximum number.
Now here are the computed properties:
data: {
strengthLevel: 24 // default strength level on pageLoad
},computed: {
generatedPassword () {
let charactersArray = 'a-z'.split(',')
let CharacterSet = ''
let password = ''
let size = 8
_switch_ (this.strengthLevel) {
_case_ 12:
size = 10
charactersArray = 'a-z,A-Z'.split(',')
_break_ _case_ 24:
size = 12
charactersArray = 'a-z,A-Z,0-9'.split(',')
_break_ _case_ 36:
size = 14
charactersArray = 'a-z,A-Z,0-9,#'.split(',')
_break_ _case_ 48:
size = 16
charactersArray = 'a-z,A-Z,0-9,#'.split(',')
_break_ } _if_ (charactersArray.indexOf('a-z') >= 0) {
CharacterSet += 'abcdefghijklmnopqrstuvwxyz'
} _if_ (charactersArray.indexOf('A-Z') >= 0) {
CharacterSet += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
}
_if_ (charactersArray.indexOf('0-9') >= 0) {
CharacterSet += '0123456789'
} _if_ (charactersArray.indexOf('#') >= 0) {
CharacterSet += '![]{}()%&*$#^~@|'
} _for_ (let i = 0; i < size; i++) {
password += CharacterSet.charAt(Math.floor(Math.random() * CharacterSet.length))
}
_return_ password
}, strengthLabel () {
_switch_ (this.strengthLevel) {
_case_ 12:
_return_ 'poor'
_case_ 24:
_return_ 'fair'
_case_ 36:
_return_ 'good'
_case_ 48:
_return_ 'excellent'
_default_:
_return_ 'weak'
}
}, strengthColor () {
_switch_ (this.strengthLevel) {
_case_ 12:
_return_ 'amber-10'
_case_ 24:
_return_ 'orange-6'
_case_ 36:
_return_ 'primary'
_case_ 48:
_return_ 'positive'
_default_:
_return_ 'blue-grey-3'
}
}
}
strengthColor return values are from Quasar color palette.
generatedPassword computed property is originally made by Christophor Wilson and I just changed a bit of it.
P.S.: One final trick for vue-progress-path styles. It has a predefined stroke-width value for the fingerprint filling action, which is pretty thick, and you can get it thinner by:
<style>
.vue-progress-path path {
stroke-width:1 !important;
}
</style>
That’s it! The rest of my code is the validations of the password fields and mutation mechanism on server side. I hope you enjoyed it. Thank you!
#vuejs #javascript