Skip to content

Instantly share code, notes, and snippets.

@kosalvann
Created June 17, 2020 04:14
Show Gist options
  • Save kosalvann/c36ea719f299b0c46019d48abd225fda to your computer and use it in GitHub Desktop.
Save kosalvann/c36ea719f299b0c46019d48abd225fda to your computer and use it in GitHub Desktop.
Random Password Generator A random password generator tool // source https://jsbin.com/juriwij
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="A random password generator tool">
<meta name="viewport" content="width=device-width">
<title>Random Password Generator</title>
<link href="https://fonts.googleapis.com/css2?family=Material+Icons&PT+Mono&Roboto:wght@400;700&display=swap" rel="stylesheet">
<style id="jsbin-css">
*, :after, :before {
font-size: 0.90rem;
font-family: 'Roboto', arial, sans-serif;
box-sizing: border-box;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
html, body {
padding: 0;
margin: 0;
background-color: #ffffff;
height: 100%;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #f3f7fa;
background: linear-gradient(345deg, #f3f7fa 0%, #ffffff 100%);
}
body * {
color: #2a354f;
font-family: 'Roboto', arial, sans-serif;
line-height: 1.43;
letter-spacing: 0.025em;
box-sizing: border-box;
-webkit-transition: all 0.5s;
transition: all 0.5s;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
width: 80%;
height: 100%;
font-size: 15px;
font-family: arial,sans-serif;
line-height: 1.2;
}
h2 {
display: flex;
flex-direction: row;
align-items: center;
font-size: 18px;
color: #2b78fe;
letter-spacing: -0.015em;
font-weight: 600;
line-height: 1.8;
}
h2 .material-icons {
margin-right: 6px;
color: #2b78fe;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
background-color: #ffffff;
border-radius: 5px;
border: 1px solid #ddd;
}
section {
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: center;
width: 100%;
}
section.head {
border-bottom: 1px solid #ddd;
}
.password {
display: flex;
align-items: center;
flex: 1;
padding: 10px 20px;
font-size: 17px;
font-family: 'PT Mono', monospace;
color: #666;
letter-spacing: 0.05em;
border: 0 none;
outline: none;
border-top-left-radius:5px;
-webkit-transition: all 0.5s;
transition: all 0.5s;
}
.head.selected .password {
color: #000;
background: #f6f6f6;
}
.head .icon {
padding: 10px;
cursor: pointer;
border-left: 1px solid #ddd;
}
.head.selected .icon {
color: #11ab7c;
}
section.settings {
padding: 20px;
}
section.settings > div {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin: 0 7px;
}
section.settings .material-icons {
margin-right: 5px;
color: #2a354f;
}
section.settings .symbols {
cursor: pointer;
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px;
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
-moz-osx-font-smoothing: grayscale;
font-feature-settings: 'liga';
}
section.range {
flex-direction: row;
align-items: center;
justify-content: center;
border-bottom: 1px solid #ddd;
padding-right: 20px;
}
section.range .output {
flex: 1 auto;
text-align: center;
margin-right: 20px;
padding: 10px 20px;
font-size: 13px;
color: #ddd;
border-right: 1px solid #ddd;
}
section.range .output .value {
font-size: 17px;
font-weight: 600;
font-family: 'PT Mono', monospace;
color: #333;
}
input[type="range"] {
-webkit-appearance: none;
width: 85%;
height: 100%;
background: transparent;
}
input[type="range"]:focus {
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 24px;
width: 24px;
border-radius: 50%;
background: #ffffff;
margin-top: -10px;
border: 2px solid rgba(0, 0, 0, 0.2);
cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
width: 60%;
height: 5px;
background: rgba(0, 0, 0, 0.1);
border-radius: 3rem;
cursor: pointer;
}
input[type="range"]::-ms-track {
width: 60%;
cursor: pointer;
height: 9px;
-ms-transition: all 0.5s;
transition: all 0.5s;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type="range"]::-ms-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: #ffffff;
margin-top: -5px;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
cursor: pointer;
}
input[type="range"]::-ms-fill-lower {
background: #bdbdbd;
border-radius: 3rem;
}
input[type="range"]:focus::-ms-fill-lower {
background: #ff6e40;
}
input[type="range"]::-ms-fill-upper {
background: #bdbdbd;
border-radius: 3rem;
}
input[type="range"]:focus::-ms-fill-upper {
background: #ff6e40;
}
input[type="range"]::-moz-range-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: #ffffff;
margin-top: -5px;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
cursor: pointer;
}
input[type="range"]::-moz-range-track {
width: 60%;
height: 9px;
background: #bdbdbd;
border-radius: 3rem;
-moz-transition: all 0.5s;
transition: all 0.5s;
cursor: pointer;
}
input[type="range"]:hover::-moz-range-track {
background: #ff6e40;
}
/*
* Media Query
*/
@media only screen and (max-width: 528px) {
#app,
.container {
width: 100%;
}
h2 {
font-size: 17px
}
section.head {
flex-direction: column;
}
.password {
flex: 1;
border-top-right-radius: 5px;
text-align: center;
}
.head .button.icon {
display: none;
}
}
</style>
</head>
<body>
<div id="app">
<h2><span class="material-icons">security</span>Password Generator</h2>
<div class="container">
<section class="head">
<input class="password" id="password" readonly="readonly"/>
<span class="copy button material-icons icon">sync</span>
</section>
<section class="range">
<div class="output">
<div>Length</div>
<span class="value">16</span>
</div>
<input id="slider" type="range" min="6" max="35" value="16">
</section>
<section class="settings">
<div class="letters">
<span class="material-icons">radio_button_checked</span>
<label>Letters</label>
</div>
<div class="numbers">
<span class="material-icons">radio_button_checked</span>
<label>Numbers</label>
</div>
<div class="symbols">
<span class="material-icons">radio_button_unchecked</span>
<label>Symbols</label>
</div>
</section>
</div>
</div>
<script id="jsbin-javascript">
let // Global variables
headSection = document.querySelector('.head')
, password = document.querySelector('.password')
, button = document.querySelector('.copy.button')
, symbolsButton = document.querySelector('.settings .symbols')
, symbolsCheckBox = document.querySelector('.symbols .material-icons')
, slider = document.querySelector('#slider')
, sliderValue = document.querySelector('.output .value')
// The initial state of the settings
, selectionState = {
'symbols': false
};
/*
* The alphanumeric characters and symbols
* used to generate passwords
*/
const CHARSET = {
'numeric' : '0123456789',
'alpha': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'symbols': '/^_@&[<->]\:{.+},$'
};
/*
* Load the functions to generate the password
*/
window.onload = (e) => {
password.value = renderPassword(slider.value, selectionState['symbols']);
// Regenerate password on these events
changePasswordOnSlide(e);
reloadPassword(e);
symbolButtonHandler(e);
};
/*
* Toggle the symbol button between true/false state
*/
const symbolButtonHandler = (e) => {
symbolsButton.addEventListener('click', (e) => {
let renderSymbol = selectionState['symbols'] = !selectionState['symbols'];
password.value = renderPassword(slider.value, renderSymbol);
// Disable/enable symbols in password
symbolsCheckBox.textContent
= selectionState['symbols']
? 'radio_button_checked'
: 'radio_button_unchecked';
});
}
/*
* Handle the copy-to-clipboard functionality
*/
const copyToClipboard = () => {
// Select & copy the password value
button.innerText = 'assignment_turned_in';
password.select();
document.execCommand('copy');
// Return to original state
setTimeout(() => {
button.innerText = 'sync';
headSection.classList.remove('selected');
}, 400);
}
/*
* The logic to generate a random string
*
* @param charset String characters use for the password
* @param len The desired length of the password via the slider
*/
const generatePassword = (charset, len) => {
var result = "";
for (var i = 0; i < len; i++) {
result += charset[Math.floor(Math.random() * 52 + 1)];
}
// Ensure we only return the exact length
return result.substr(0, len);
}
/*
* The logic to regenerate password when using the slider
*/
const changePasswordOnSlide = (e) => {
slider.oninput = (e) => {
sliderValue.textContent = slider.value;
setTimeout(() => {
// Generate password on slide
password.value = renderPassword(slider.value);
headSection.classList.add('selected');
copyToClipboard();
// Return to original state
setTimeout(() => {
headSection.classList.remove('selected');
}, 400);
}, 0)
};
}
/*
* The logic to regenerate password when
* the reload button is clicked
*/
const reloadPassword = (e) => {
button.addEventListener('click', (e) => {
setTimeout(() => {
copyToClipboard();
}, 0
, password.value = renderPassword(slider.value)
, headSection.classList.add('selected')
)
})
}
/*
* Determine if the symbol is enabled and merge all of the combined
* alphanumeric characters and symbol from the charset
*
* @param len The desired length of the password via the slider
* @param renderSymbols Determined if symbol are included in the password
*/
const renderPassword = (len, renderSymbols = selectionState['symbols']) => {
let charSet = CHARSET['numeric'].split('').concat(
renderSymbols ? CHARSET['symbols'].split('') : [],
CHARSET['alpha'].split('')
);
return generatePassword(charSet, len)
}
</script>
<script id="jsbin-source-css" type="text/css">*, :after, :before {
font-size: 0.90rem;
font-family: 'Roboto', arial, sans-serif;
box-sizing: border-box;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
html, body {
padding: 0;
margin: 0;
background-color: #ffffff;
height: 100%;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #f3f7fa;
background: linear-gradient(345deg, #f3f7fa 0%, #ffffff 100%);
}
body * {
color: #2a354f;
font-family: 'Roboto', arial, sans-serif;
line-height: 1.43;
letter-spacing: 0.025em;
box-sizing: border-box;
-webkit-transition: all 0.5s;
transition: all 0.5s;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
width: 80%;
height: 100%;
font-size: 15px;
font-family: arial,sans-serif;
line-height: 1.2;
}
h2 {
display: flex;
flex-direction: row;
align-items: center;
font-size: 18px;
color: #2b78fe;
letter-spacing: -0.015em;
font-weight: 600;
line-height: 1.8;
}
h2 .material-icons {
margin-right: 6px;
color: #2b78fe;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
background-color: #ffffff;
border-radius: 5px;
border: 1px solid #ddd;
}
section {
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: center;
width: 100%;
}
section.head {
border-bottom: 1px solid #ddd;
}
.password {
display: flex;
align-items: center;
flex: 1;
padding: 10px 20px;
font-size: 17px;
font-family: 'PT Mono', monospace;
color: #666;
letter-spacing: 0.05em;
border: 0 none;
outline: none;
border-top-left-radius:5px;
-webkit-transition: all 0.5s;
transition: all 0.5s;
}
.head.selected .password {
color: #000;
background: #f6f6f6;
}
.head .icon {
padding: 10px;
cursor: pointer;
border-left: 1px solid #ddd;
}
.head.selected .icon {
color: #11ab7c;
}
section.settings {
padding: 20px;
}
section.settings > div {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin: 0 7px;
}
section.settings .material-icons {
margin-right: 5px;
color: #2a354f;
}
section.settings .symbols {
cursor: pointer;
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px;
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
-moz-osx-font-smoothing: grayscale;
font-feature-settings: 'liga';
}
section.range {
flex-direction: row;
align-items: center;
justify-content: center;
border-bottom: 1px solid #ddd;
padding-right: 20px;
}
section.range .output {
flex: 1 auto;
text-align: center;
margin-right: 20px;
padding: 10px 20px;
font-size: 13px;
color: #ddd;
border-right: 1px solid #ddd;
}
section.range .output .value {
font-size: 17px;
font-weight: 600;
font-family: 'PT Mono', monospace;
color: #333;
}
input[type="range"] {
-webkit-appearance: none;
width: 85%;
height: 100%;
background: transparent;
}
input[type="range"]:focus {
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 24px;
width: 24px;
border-radius: 50%;
background: #ffffff;
margin-top: -10px;
border: 2px solid rgba(0, 0, 0, 0.2);
cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
width: 60%;
height: 5px;
background: rgba(0, 0, 0, 0.1);
border-radius: 3rem;
cursor: pointer;
}
input[type="range"]::-ms-track {
width: 60%;
cursor: pointer;
height: 9px;
-ms-transition: all 0.5s;
transition: all 0.5s;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type="range"]::-ms-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: #ffffff;
margin-top: -5px;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
cursor: pointer;
}
input[type="range"]::-ms-fill-lower {
background: #bdbdbd;
border-radius: 3rem;
}
input[type="range"]:focus::-ms-fill-lower {
background: #ff6e40;
}
input[type="range"]::-ms-fill-upper {
background: #bdbdbd;
border-radius: 3rem;
}
input[type="range"]:focus::-ms-fill-upper {
background: #ff6e40;
}
input[type="range"]::-moz-range-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: #ffffff;
margin-top: -5px;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
cursor: pointer;
}
input[type="range"]::-moz-range-track {
width: 60%;
height: 9px;
background: #bdbdbd;
border-radius: 3rem;
-moz-transition: all 0.5s;
transition: all 0.5s;
cursor: pointer;
}
input[type="range"]:hover::-moz-range-track {
background: #ff6e40;
}
/*
* Media Query
*/
@media only screen and (max-width: 528px) {
#app,
.container {
width: 100%;
}
h2 {
font-size: 17px
}
section.head {
flex-direction: column;
}
.password {
flex: 1;
border-top-right-radius: 5px;
text-align: center;
}
.head .button.icon {
display: none;
}
}
</script>
<script id="jsbin-source-javascript" type="text/javascript">let // Global variables
headSection = document.querySelector('.head')
, password = document.querySelector('.password')
, button = document.querySelector('.copy.button')
, symbolsButton = document.querySelector('.settings .symbols')
, symbolsCheckBox = document.querySelector('.symbols .material-icons')
, slider = document.querySelector('#slider')
, sliderValue = document.querySelector('.output .value')
// The initial state of the settings
, selectionState = {
'symbols': false
};
/*
* The alphanumeric characters and symbols
* used to generate passwords
*/
const CHARSET = {
'numeric' : '0123456789',
'alpha': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'symbols': '/^_@&[<->]\:{.+},$'
};
/*
* Load the functions to generate the password
*/
window.onload = (e) => {
password.value = renderPassword(slider.value, selectionState['symbols']);
// Regenerate password on these events
changePasswordOnSlide(e);
reloadPassword(e);
symbolButtonHandler(e);
};
/*
* Toggle the symbol button between true/false state
*/
const symbolButtonHandler = (e) => {
symbolsButton.addEventListener('click', (e) => {
let renderSymbol = selectionState['symbols'] = !selectionState['symbols'];
password.value = renderPassword(slider.value, renderSymbol);
// Disable/enable symbols in password
symbolsCheckBox.textContent
= selectionState['symbols']
? 'radio_button_checked'
: 'radio_button_unchecked';
});
}
/*
* Handle the copy-to-clipboard functionality
*/
const copyToClipboard = () => {
// Select & copy the password value
button.innerText = 'assignment_turned_in';
password.select();
document.execCommand('copy');
// Return to original state
setTimeout(() => {
button.innerText = 'sync';
headSection.classList.remove('selected');
}, 400);
}
/*
* The logic to generate a random string
*
* @param charset String characters use for the password
* @param len The desired length of the password via the slider
*/
const generatePassword = (charset, len) => {
var result = "";
for (var i = 0; i < len; i++) {
result += charset[Math.floor(Math.random() * 52 + 1)];
}
// Ensure we only return the exact length
return result.substr(0, len);
}
/*
* The logic to regenerate password when using the slider
*/
const changePasswordOnSlide = (e) => {
slider.oninput = (e) => {
sliderValue.textContent = slider.value;
setTimeout(() => {
// Generate password on slide
password.value = renderPassword(slider.value);
headSection.classList.add('selected');
copyToClipboard();
// Return to original state
setTimeout(() => {
headSection.classList.remove('selected');
}, 400);
}, 0)
};
}
/*
* The logic to regenerate password when
* the reload button is clicked
*/
const reloadPassword = (e) => {
button.addEventListener('click', (e) => {
setTimeout(() => {
copyToClipboard();
}, 0
, password.value = renderPassword(slider.value)
, headSection.classList.add('selected')
)
})
}
/*
* Determine if the symbol is enabled and merge all of the combined
* alphanumeric characters and symbol from the charset
*
* @param len The desired length of the password via the slider
* @param renderSymbols Determined if symbol are included in the password
*/
const renderPassword = (len, renderSymbols = selectionState['symbols']) => {
let charSet = CHARSET['numeric'].split('').concat(
renderSymbols ? CHARSET['symbols'].split('') : [],
CHARSET['alpha'].split('')
);
return generatePassword(charSet, len)
}
</script></body>
</html>
*, :after, :before {
font-size: 0.90rem;
font-family: 'Roboto', arial, sans-serif;
box-sizing: border-box;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
html, body {
padding: 0;
margin: 0;
background-color: #ffffff;
height: 100%;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #f3f7fa;
background: linear-gradient(345deg, #f3f7fa 0%, #ffffff 100%);
}
body * {
color: #2a354f;
font-family: 'Roboto', arial, sans-serif;
line-height: 1.43;
letter-spacing: 0.025em;
box-sizing: border-box;
-webkit-transition: all 0.5s;
transition: all 0.5s;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
width: 80%;
height: 100%;
font-size: 15px;
font-family: arial,sans-serif;
line-height: 1.2;
}
h2 {
display: flex;
flex-direction: row;
align-items: center;
font-size: 18px;
color: #2b78fe;
letter-spacing: -0.015em;
font-weight: 600;
line-height: 1.8;
}
h2 .material-icons {
margin-right: 6px;
color: #2b78fe;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
background-color: #ffffff;
border-radius: 5px;
border: 1px solid #ddd;
}
section {
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: center;
width: 100%;
}
section.head {
border-bottom: 1px solid #ddd;
}
.password {
display: flex;
align-items: center;
flex: 1;
padding: 10px 20px;
font-size: 17px;
font-family: 'PT Mono', monospace;
color: #666;
letter-spacing: 0.05em;
border: 0 none;
outline: none;
border-top-left-radius:5px;
-webkit-transition: all 0.5s;
transition: all 0.5s;
}
.head.selected .password {
color: #000;
background: #f6f6f6;
}
.head .icon {
padding: 10px;
cursor: pointer;
border-left: 1px solid #ddd;
}
.head.selected .icon {
color: #11ab7c;
}
section.settings {
padding: 20px;
}
section.settings > div {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin: 0 7px;
}
section.settings .material-icons {
margin-right: 5px;
color: #2a354f;
}
section.settings .symbols {
cursor: pointer;
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px;
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
-moz-osx-font-smoothing: grayscale;
font-feature-settings: 'liga';
}
section.range {
flex-direction: row;
align-items: center;
justify-content: center;
border-bottom: 1px solid #ddd;
padding-right: 20px;
}
section.range .output {
flex: 1 auto;
text-align: center;
margin-right: 20px;
padding: 10px 20px;
font-size: 13px;
color: #ddd;
border-right: 1px solid #ddd;
}
section.range .output .value {
font-size: 17px;
font-weight: 600;
font-family: 'PT Mono', monospace;
color: #333;
}
input[type="range"] {
-webkit-appearance: none;
width: 85%;
height: 100%;
background: transparent;
}
input[type="range"]:focus {
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 24px;
width: 24px;
border-radius: 50%;
background: #ffffff;
margin-top: -10px;
border: 2px solid rgba(0, 0, 0, 0.2);
cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
width: 60%;
height: 5px;
background: rgba(0, 0, 0, 0.1);
border-radius: 3rem;
cursor: pointer;
}
input[type="range"]::-ms-track {
width: 60%;
cursor: pointer;
height: 9px;
-ms-transition: all 0.5s;
transition: all 0.5s;
background: transparent;
border-color: transparent;
color: transparent;
}
input[type="range"]::-ms-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: #ffffff;
margin-top: -5px;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
cursor: pointer;
}
input[type="range"]::-ms-fill-lower {
background: #bdbdbd;
border-radius: 3rem;
}
input[type="range"]:focus::-ms-fill-lower {
background: #ff6e40;
}
input[type="range"]::-ms-fill-upper {
background: #bdbdbd;
border-radius: 3rem;
}
input[type="range"]:focus::-ms-fill-upper {
background: #ff6e40;
}
input[type="range"]::-moz-range-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: #ffffff;
margin-top: -5px;
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
cursor: pointer;
}
input[type="range"]::-moz-range-track {
width: 60%;
height: 9px;
background: #bdbdbd;
border-radius: 3rem;
-moz-transition: all 0.5s;
transition: all 0.5s;
cursor: pointer;
}
input[type="range"]:hover::-moz-range-track {
background: #ff6e40;
}
/*
* Media Query
*/
@media only screen and (max-width: 528px) {
#app,
.container {
width: 100%;
}
h2 {
font-size: 17px
}
section.head {
flex-direction: column;
}
.password {
flex: 1;
border-top-right-radius: 5px;
text-align: center;
}
.head .button.icon {
display: none;
}
}
let // Global variables
headSection = document.querySelector('.head')
, password = document.querySelector('.password')
, button = document.querySelector('.copy.button')
, symbolsButton = document.querySelector('.settings .symbols')
, symbolsCheckBox = document.querySelector('.symbols .material-icons')
, slider = document.querySelector('#slider')
, sliderValue = document.querySelector('.output .value')
// The initial state of the settings
, selectionState = {
'symbols': false
};
/*
* The alphanumeric characters and symbols
* used to generate passwords
*/
const CHARSET = {
'numeric' : '0123456789',
'alpha': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'symbols': '/^_@&[<->]\:{.+},$'
};
/*
* Load the functions to generate the password
*/
window.onload = (e) => {
password.value = renderPassword(slider.value, selectionState['symbols']);
// Regenerate password on these events
changePasswordOnSlide(e);
reloadPassword(e);
symbolButtonHandler(e);
};
/*
* Toggle the symbol button between true/false state
*/
const symbolButtonHandler = (e) => {
symbolsButton.addEventListener('click', (e) => {
let renderSymbol = selectionState['symbols'] = !selectionState['symbols'];
password.value = renderPassword(slider.value, renderSymbol);
// Disable/enable symbols in password
symbolsCheckBox.textContent
= selectionState['symbols']
? 'radio_button_checked'
: 'radio_button_unchecked';
});
}
/*
* Handle the copy-to-clipboard functionality
*/
const copyToClipboard = () => {
// Select & copy the password value
button.innerText = 'assignment_turned_in';
password.select();
document.execCommand('copy');
// Return to original state
setTimeout(() => {
button.innerText = 'sync';
headSection.classList.remove('selected');
}, 400);
}
/*
* The logic to generate a random string
*
* @param charset String characters use for the password
* @param len The desired length of the password via the slider
*/
const generatePassword = (charset, len) => {
var result = "";
for (var i = 0; i < len; i++) {
result += charset[Math.floor(Math.random() * 52 + 1)];
}
// Ensure we only return the exact length
return result.substr(0, len);
}
/*
* The logic to regenerate password when using the slider
*/
const changePasswordOnSlide = (e) => {
slider.oninput = (e) => {
sliderValue.textContent = slider.value;
setTimeout(() => {
// Generate password on slide
password.value = renderPassword(slider.value);
headSection.classList.add('selected');
copyToClipboard();
// Return to original state
setTimeout(() => {
headSection.classList.remove('selected');
}, 400);
}, 0)
};
}
/*
* The logic to regenerate password when
* the reload button is clicked
*/
const reloadPassword = (e) => {
button.addEventListener('click', (e) => {
setTimeout(() => {
copyToClipboard();
}, 0
, password.value = renderPassword(slider.value)
, headSection.classList.add('selected')
)
})
}
/*
* Determine if the symbol is enabled and merge all of the combined
* alphanumeric characters and symbol from the charset
*
* @param len The desired length of the password via the slider
* @param renderSymbols Determined if symbol are included in the password
*/
const renderPassword = (len, renderSymbols = selectionState['symbols']) => {
let charSet = CHARSET['numeric'].split('').concat(
renderSymbols ? CHARSET['symbols'].split('') : [],
CHARSET['alpha'].split('')
);
return generatePassword(charSet, len)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment