├── README.md ├── css ├── style.css ├── style.css.map └── style.scss ├── img ├── Screenshot from 2020-01-01 03-54-29.png └── Screenshot from 2020-01-01 03-54-50.png ├── index.html └── js └── script.js /README.md: -------------------------------------------------------------------------------- 1 | # password-generator 2 | 3 | Create random **passwords** using the password **generator** tool. 4 | 5 | Demo: https://codepen.io/dev_loop/full/vYYxvbz 6 | 7 | ![Tool](https://github.com/devloop01/password-generator/blob/master/img/Screenshot%20from%202020-01-01%2003-54-29.png) 8 | 9 | After selecting the desired options for the password, click **generate** to generate 10 | 11 | a new password with selected options. 12 | 13 | ![password](https://github.com/devloop01/password-generator/blob/master/img/Screenshot%20from%202020-01-01%2003-54-50.png) 14 | 15 | Then click the password area to copy the password to clipboard. 16 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | -webkit-box-sizing: border-box; 5 | box-sizing: border-box; 6 | } 7 | 8 | body { 9 | width: 100%; 10 | height: 100%; 11 | background-image: -webkit-gradient(linear, left bottom, left top, color-stop(100%, #209cff), color-stop(200%, #68e0cf)); 12 | background-image: linear-gradient(to top, #209cff 100%, #68e0cf 200%); 13 | display: -webkit-box; 14 | display: -ms-flexbox; 15 | display: flex; 16 | -webkit-box-pack: center; 17 | -ms-flex-pack: center; 18 | justify-content: center; 19 | -webkit-box-align: center; 20 | -ms-flex-align: center; 21 | align-items: center; 22 | } 23 | 24 | button { 25 | border: 0; 26 | outline: 0; 27 | } 28 | 29 | .container { 30 | margin: 40px 0; 31 | width: 400px; 32 | height: 600px; 33 | padding: 10px 25px; 34 | background: #0a0e31; 35 | border-radius: 10px; 36 | -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.45), 0 4px 8px rgba(0, 0, 0, 0.35), 0 8px 12px rgba(0, 0, 0, 0.15); 37 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.45), 0 4px 8px rgba(0, 0, 0, 0.35), 0 8px 12px rgba(0, 0, 0, 0.15); 38 | font-family: "Montserrat"; 39 | } 40 | 41 | .container h2.title { 42 | font-size: 1.75rem; 43 | margin: 10px -5px; 44 | margin-bottom: 30px; 45 | color: #fff; 46 | } 47 | 48 | .result { 49 | position: relative; 50 | width: 100%; 51 | height: 65px; 52 | overflow: hidden; 53 | } 54 | 55 | .result__info { 56 | position: absolute; 57 | bottom: 4px; 58 | color: #fff; 59 | font-size: 0.8rem; 60 | -webkit-transition: all 150ms ease-in-out; 61 | transition: all 150ms ease-in-out; 62 | -webkit-transform: translateY(200%); 63 | transform: translateY(200%); 64 | opacity: 0; 65 | } 66 | 67 | .result__info.right { 68 | right: 8px; 69 | } 70 | 71 | .result__info.left { 72 | left: 8px; 73 | } 74 | 75 | .result__viewbox { 76 | width: 100%; 77 | height: 100%; 78 | background: rgba(255, 255, 255, 0.08); 79 | border-radius: 8px; 80 | color: #fff; 81 | text-align: center; 82 | line-height: 65px; 83 | } 84 | 85 | .result #copy-btn { 86 | position: absolute; 87 | top: var(--y); 88 | left: var(--x); 89 | width: 38px; 90 | height: 38px; 91 | background: #fff; 92 | border-radius: 50%; 93 | opacity: 0; 94 | -webkit-transform: translate(-50%, -50%) scale(0); 95 | transform: translate(-50%, -50%) scale(0); 96 | -webkit-transition: all 350ms cubic-bezier(0.175, 0.885, 0.32, 1.275); 97 | transition: all 350ms cubic-bezier(0.175, 0.885, 0.32, 1.275); 98 | cursor: pointer; 99 | z-index: 2; 100 | } 101 | 102 | .result #copy-btn:active { 103 | -webkit-box-shadow: 0 0 0 200px rgba(255, 255, 255, 0.08); 104 | box-shadow: 0 0 0 200px rgba(255, 255, 255, 0.08); 105 | } 106 | 107 | .result:hover #copy-btn { 108 | opacity: 1; 109 | -webkit-transform: translate(-50%, -50%) scale(1.35); 110 | transform: translate(-50%, -50%) scale(1.35); 111 | } 112 | 113 | .field-title { 114 | position: absolute; 115 | top: -10px; 116 | left: 8px; 117 | -webkit-transform: translateY(-50%); 118 | transform: translateY(-50%); 119 | font-weight: 800; 120 | color: rgba(255, 255, 255, 0.5); 121 | text-transform: uppercase; 122 | font-size: 0.65rem; 123 | pointer-events: none; 124 | -webkit-user-select: none; 125 | -moz-user-select: none; 126 | -ms-user-select: none; 127 | user-select: none; 128 | } 129 | 130 | .options { 131 | width: 100%; 132 | height: auto; 133 | margin: 50px 0; 134 | } 135 | 136 | .range__slider { 137 | position: relative; 138 | width: 100%; 139 | height: calc(65px - 10px); 140 | display: -webkit-box; 141 | display: -ms-flexbox; 142 | display: flex; 143 | -webkit-box-pack: center; 144 | -ms-flex-pack: center; 145 | justify-content: center; 146 | -webkit-box-align: center; 147 | -ms-flex-align: center; 148 | align-items: center; 149 | background: rgba(255, 255, 255, 0.08); 150 | border-radius: 8px; 151 | margin: 30px 0; 152 | } 153 | 154 | .range__slider::before, .range__slider::after { 155 | position: absolute; 156 | color: #fff; 157 | font-size: 0.9rem; 158 | font-weight: bold; 159 | } 160 | 161 | .range__slider::before { 162 | content: attr(data-min); 163 | left: 10px; 164 | } 165 | 166 | .range__slider::after { 167 | content: attr(data-max); 168 | right: 10px; 169 | } 170 | 171 | .range__slider .length__title::after { 172 | content: attr(data-length); 173 | position: absolute; 174 | right: -16px; 175 | font-variant-numeric: tabular-nums; 176 | color: #fff; 177 | } 178 | 179 | #slider { 180 | -webkit-appearance: none; 181 | width: calc(100% - (70px)); 182 | height: 2px; 183 | border-radius: 5px; 184 | background: rgba(255, 255, 255, 0.314); 185 | outline: none; 186 | padding: 0; 187 | margin: 0; 188 | cursor: pointer; 189 | } 190 | 191 | #slider::-webkit-slider-thumb { 192 | -webkit-appearance: none; 193 | width: 20px; 194 | height: 20px; 195 | border-radius: 50%; 196 | background: white; 197 | cursor: pointer; 198 | -webkit-transition: all 0.15s ease-in-out; 199 | transition: all 0.15s ease-in-out; 200 | } 201 | 202 | #slider::-webkit-slider-thumb:hover { 203 | background: #d4d4d4; 204 | -webkit-transform: scale(1.2); 205 | transform: scale(1.2); 206 | } 207 | 208 | #slider::-moz-range-thumb { 209 | width: 20px; 210 | height: 20px; 211 | border: 0; 212 | border-radius: 50%; 213 | background: white; 214 | cursor: pointer; 215 | -webkit-transition: background 0.15s ease-in-out; 216 | transition: background 0.15s ease-in-out; 217 | } 218 | 219 | #slider::-moz-range-thumb:hover { 220 | background: #d4d4d4; 221 | } 222 | 223 | .settings { 224 | position: relative; 225 | height: auto; 226 | widows: 100%; 227 | display: -webkit-box; 228 | display: -ms-flexbox; 229 | display: flex; 230 | -webkit-box-orient: vertical; 231 | -webkit-box-direction: normal; 232 | -ms-flex-direction: column; 233 | flex-direction: column; 234 | } 235 | 236 | .settings .setting { 237 | position: relative; 238 | width: 100%; 239 | height: calc(65px - 10px); 240 | background: rgba(255, 255, 255, 0.08); 241 | border-radius: 8px; 242 | display: -webkit-box; 243 | display: -ms-flexbox; 244 | display: flex; 245 | -webkit-box-align: center; 246 | -ms-flex-align: center; 247 | align-items: center; 248 | padding: 10px 25px; 249 | color: #fff; 250 | margin-bottom: 8px; 251 | } 252 | 253 | .settings .setting input { 254 | opacity: 0; 255 | position: absolute; 256 | } 257 | 258 | .settings .setting input + label { 259 | -webkit-user-select: none; 260 | -moz-user-select: none; 261 | -ms-user-select: none; 262 | user-select: none; 263 | } 264 | 265 | .settings .setting input + label::before, .settings .setting input + label::after { 266 | content: ""; 267 | position: absolute; 268 | -webkit-transition: 150ms cubic-bezier(0.24, 0, 0.5, 1); 269 | transition: 150ms cubic-bezier(0.24, 0, 0.5, 1); 270 | -webkit-transform: translateY(-50%); 271 | transform: translateY(-50%); 272 | top: 50%; 273 | right: 10px; 274 | cursor: pointer; 275 | } 276 | 277 | .settings .setting input + label::before { 278 | height: 30px; 279 | width: 50px; 280 | border-radius: 30px; 281 | background: rgba(214, 214, 214, 0.434); 282 | } 283 | 284 | .settings .setting input + label::after { 285 | height: 24px; 286 | width: 24px; 287 | border-radius: 60px; 288 | right: 32px; 289 | background: #fff; 290 | } 291 | 292 | .settings .setting input:checked + label:before { 293 | background: #5d68e2; 294 | -webkit-transition: all 150ms cubic-bezier(0, 0, 0, 0.1); 295 | transition: all 150ms cubic-bezier(0, 0, 0, 0.1); 296 | } 297 | 298 | .settings .setting input:checked + label:after { 299 | right: 14px; 300 | } 301 | 302 | .settings .setting input:focus + label:before { 303 | -webkit-box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.75); 304 | box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.75); 305 | } 306 | 307 | .btn.generate { 308 | -webkit-user-select: none; 309 | -moz-user-select: none; 310 | -ms-user-select: none; 311 | user-select: none; 312 | position: relative; 313 | width: 100%; 314 | height: 50px; 315 | margin: 10px 0; 316 | border-radius: 8px; 317 | color: #fff; 318 | border: none; 319 | background-image: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 320 | letter-spacing: 1px; 321 | font-weight: bold; 322 | text-transform: uppercase; 323 | cursor: pointer; 324 | -webkit-transition: all 150ms ease; 325 | transition: all 150ms ease; 326 | } 327 | 328 | .btn.generate:active { 329 | -webkit-transform: translateY(-3%); 330 | transform: translateY(-3%); 331 | -webkit-box-shadow: 0 4px 8px rgba(255, 255, 255, 0.08); 332 | box-shadow: 0 4px 8px rgba(255, 255, 255, 0.08); 333 | } 334 | /*# sourceMappingURL=style.css.map */ -------------------------------------------------------------------------------- /css/style.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "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", 4 | "sources": [ 5 | "style.scss" 6 | ], 7 | "names": [], 8 | "file": "style.css" 9 | } -------------------------------------------------------------------------------- /css/style.scss: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | body { 7 | width: 100%; 8 | height: 100%; 9 | background-image: linear-gradient(to top, #209cff 100%, #68e0cf 200%); 10 | display: flex; 11 | justify-content: center; 12 | align-items: center; 13 | } 14 | button { 15 | border: 0; 16 | outline: 0; 17 | } 18 | 19 | .container { 20 | margin: 40px 0; 21 | width: 400px; 22 | height: 600px; 23 | padding: 10px 25px; 24 | background: #0a0e31; 25 | border-radius: 10px; 26 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.45), 0 4px 8px rgba(0, 0, 0, 0.35), 0 8px 12px rgba(0, 0, 0, 0.15); 27 | font-family: "Montserrat"; 28 | h2.title { 29 | font-size: 1.75rem; 30 | margin: 10px -5px; 31 | margin-bottom: 30px; 32 | color: #fff; 33 | } 34 | } 35 | 36 | $field-color: rgba(255, 255, 255, 0.08); 37 | $field-height: 65px; 38 | $field-border-radius: 8px; 39 | 40 | .result { 41 | position: relative; 42 | width: 100%; 43 | height: 65px; 44 | overflow: hidden; 45 | &__info { 46 | &.right { 47 | right: 8px; 48 | } 49 | &.left { 50 | left: 8px; 51 | } 52 | position: absolute; 53 | bottom: 4px; 54 | color: #fff; 55 | font-size: 0.8rem; 56 | transition: all 150ms ease-in-out; 57 | transform: translateY(200%); 58 | opacity: 0; 59 | } 60 | &__viewbox { 61 | width: 100%; 62 | height: 100%; 63 | background: $field-color; 64 | border-radius: $field-border-radius; 65 | color: #fff; 66 | text-align: center; 67 | line-height: 65px; 68 | } 69 | #copy-btn { 70 | position: absolute; 71 | top: var(--y); 72 | left: var(--x); 73 | width: 38px; 74 | height: 38px; 75 | background: #fff; 76 | border-radius: 50%; 77 | opacity: 0; 78 | transform: translate(-50%, -50%) scale(0); 79 | transition: all 350ms cubic-bezier(0.175, 0.885, 0.32, 1.275); 80 | cursor: pointer; 81 | z-index: 2; 82 | &:active { 83 | box-shadow: 0 0 0 200px rgba(255, 255, 255, 0.08); 84 | } 85 | } 86 | &:hover { 87 | #copy-btn { 88 | opacity: 1; 89 | transform: translate(-50%, -50%) scale(1.35); 90 | } 91 | } 92 | } 93 | .field-title { 94 | position: absolute; 95 | top: -10px; 96 | left: 8px; 97 | transform: translateY(-50%); 98 | font-weight: 800; 99 | color: rgba(255, 255, 255, 0.5); 100 | text-transform: uppercase; 101 | font-size: 0.65rem; 102 | pointer-events: none; 103 | user-select: none; 104 | } 105 | 106 | .options { 107 | width: 100%; 108 | height: auto; 109 | margin: 50px 0; 110 | } 111 | .range__slider { 112 | position: relative; 113 | width: 100%; 114 | height: calc(#{$field-height} - 10px); 115 | display: flex; 116 | justify-content: center; 117 | align-items: center; 118 | background: $field-color; 119 | border-radius: $field-border-radius; 120 | margin: 30px 0; 121 | 122 | &::before, 123 | &::after { 124 | position: absolute; 125 | color: #fff; 126 | font-size: 0.9rem; 127 | font-weight: bold; 128 | } 129 | &::before { 130 | content: attr(data-min); 131 | left: 10px; 132 | } 133 | &::after { 134 | content: attr(data-max); 135 | right: 10px; 136 | } 137 | .length__title::after { 138 | content: attr(data-length); 139 | position: absolute; 140 | right: -16px; 141 | font-variant-numeric: tabular-nums; 142 | color: #fff; 143 | } 144 | } 145 | 146 | $range-handle-color: rgb(255, 255, 255) !default; 147 | $range-handle-color-hover: rgb(212, 212, 212) !default; 148 | $range-handle-size: 20px !default; 149 | 150 | $range-track-color: rgba(255, 255, 255, 0.314) !default; 151 | $range-track-height: 2px !default; 152 | 153 | $range-label-width: 60px !default; 154 | 155 | #slider { 156 | -webkit-appearance: none; 157 | width: calc(100% - (#{$range-label-width + 10px})); 158 | height: $range-track-height; 159 | border-radius: 5px; 160 | background: $range-track-color; 161 | outline: none; 162 | padding: 0; 163 | margin: 0; 164 | cursor: pointer; 165 | 166 | // Range Handle 167 | &::-webkit-slider-thumb { 168 | -webkit-appearance: none; 169 | width: $range-handle-size; 170 | height: $range-handle-size; 171 | border-radius: 50%; 172 | background: $range-handle-color; 173 | cursor: pointer; 174 | transition: all 0.15s ease-in-out; 175 | &:hover { 176 | background: $range-handle-color-hover; 177 | transform: scale(1.2); 178 | } 179 | } 180 | &::-moz-range-thumb { 181 | width: $range-handle-size; 182 | height: $range-handle-size; 183 | border: 0; 184 | border-radius: 50%; 185 | background: $range-handle-color; 186 | cursor: pointer; 187 | transition: background 0.15s ease-in-out; 188 | &:hover { 189 | background: $range-handle-color-hover; 190 | } 191 | } 192 | } 193 | 194 | .settings { 195 | position: relative; 196 | height: auto; 197 | widows: 100%; 198 | display: flex; 199 | flex-direction: column; 200 | 201 | .setting { 202 | position: relative; 203 | width: 100%; 204 | height: calc(#{$field-height} - 10px); 205 | background: $field-color; 206 | border-radius: $field-border-radius; 207 | display: flex; 208 | align-items: center; 209 | padding: 10px 25px; 210 | color: #fff; 211 | margin-bottom: 8px; 212 | input { 213 | opacity: 0; 214 | position: absolute; 215 | + label { 216 | user-select: none; 217 | &::before, 218 | &::after { 219 | content: ""; 220 | position: absolute; 221 | transition: 150ms cubic-bezier(0.24, 0, 0.5, 1); 222 | transform: translateY(-50%); 223 | top: 50%; 224 | right: 10px; 225 | cursor: pointer; 226 | } 227 | &::before { 228 | height: 30px; 229 | width: 50px; 230 | border-radius: 30px; 231 | background: rgba(214, 214, 214, 0.434); 232 | } 233 | &::after { 234 | height: 24px; 235 | width: 24px; 236 | border-radius: 60px; 237 | right: 32px; 238 | background: #fff; 239 | } 240 | } 241 | &:checked { 242 | & + label:before { 243 | background: #5d68e2; 244 | transition: all 150ms cubic-bezier(0, 0, 0, 0.1); 245 | } 246 | & + label:after { 247 | right: 14px; 248 | } 249 | } 250 | &:focus { 251 | + label:before { 252 | box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.75); 253 | } 254 | } 255 | &:disabled{ 256 | + label{ 257 | &:before, &:after{ cursor: not-allowed } 258 | &:before{ background: #4f4f6a } 259 | &:after{ background: #909090 } 260 | } 261 | } 262 | } 263 | } 264 | } 265 | 266 | .btn.generate { 267 | user-select: none; 268 | position: relative; 269 | width: 100%; 270 | height: 50px; 271 | margin: 10px 0; 272 | border-radius: $field-border-radius; 273 | color: #fff; 274 | border: none; 275 | background-image: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 276 | letter-spacing: 1px; 277 | font-weight: bold; 278 | text-transform: uppercase; 279 | cursor: pointer; 280 | transition: all 150ms ease; 281 | &:active { 282 | transform: translateY(-3%); 283 | box-shadow: 0 4px 8px rgba(255, 255, 255, 0.08); 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /img/Screenshot from 2020-01-01 03-54-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/password-generator/06d8c7d04cd102c1509d3f59fcb956f1fc9b6890/img/Screenshot from 2020-01-01 03-54-29.png -------------------------------------------------------------------------------- /img/Screenshot from 2020-01-01 03-54-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devloop01/password-generator/06d8c7d04cd102c1509d3f59fcb956f1fc9b6890/img/Screenshot from 2020-01-01 03-54-50.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Password Generator 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

Password Generator

17 |
18 |
Generated Password
19 |
click to copy
20 |
copied
21 |
CLICK GENERATE
22 | 23 |
24 |
25 |
length:
26 | 27 |
28 | 29 |
30 | settings 31 |
32 | 33 | 34 |
35 |
36 | 37 | 38 |
39 |
40 | 41 | 42 |
43 |
44 | 45 | 46 |
47 |
48 | 49 | 50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /js/script.js: -------------------------------------------------------------------------------- 1 | // This is a simple Password Generator App that will generate random password maybe you can you them to secure your account. 2 | // I tried my best to make the code as simple as possible please dont mind the variable names. 3 | // Also this idea came in my mind after checking Traversy Media's latest video. 4 | 5 | // Clear the concole on every refresh 6 | console.clear(); 7 | // set the body to full height 8 | // document.body.style.height = `${innerHeight}px` 9 | 10 | // Range Slider Properties. 11 | // Fill : The trailing color that you see when you drag the slider. 12 | // background : Default Range Slider Background 13 | const sliderProps = { 14 | fill: "#0B1EDF", 15 | background: "rgba(255, 255, 255, 0.214)", 16 | }; 17 | 18 | // Selecting the Range Slider container which will effect the LENGTH property of the password. 19 | const slider = document.querySelector(".range__slider"); 20 | 21 | // Text which will show the value of the range slider. 22 | const sliderValue = document.querySelector(".length__title"); 23 | 24 | // Using Event Listener to apply the fill and also change the value of the text. 25 | slider.querySelector("input").addEventListener("input", event => { 26 | sliderValue.setAttribute("data-length", event.target.value); 27 | applyFill(event.target); 28 | }); 29 | // Selecting the range input and passing it in the applyFill func. 30 | applyFill(slider.querySelector("input")); 31 | // This function is responsible to create the trailing color and setting the fill. 32 | function applyFill(slider) { 33 | const percentage = (100 * (slider.value - slider.min)) / (slider.max - slider.min); 34 | const bg = `linear-gradient(90deg, ${sliderProps.fill} ${percentage}%, ${sliderProps.background} ${percentage + 35 | 0.1}%)`; 36 | slider.style.background = bg; 37 | sliderValue.setAttribute("data-length", slider.value); 38 | } 39 | 40 | // Object of all the function names that we will use to create random letters of password 41 | const randomFunc = { 42 | lower: getRandomLower, 43 | upper: getRandomUpper, 44 | number: getRandomNumber, 45 | symbol: getRandomSymbol, 46 | }; 47 | 48 | // Random more secure value 49 | function secureMathRandom() { 50 | return window.crypto.getRandomValues(new Uint32Array(1))[0] / (Math.pow(2, 32) - 1); 51 | } 52 | 53 | // Generator Functions 54 | // All the functions that are responsible to return a random value taht we will use to create password. 55 | function getRandomLower() { 56 | return String.fromCharCode(Math.floor(Math.random() * 26) + 97); 57 | } 58 | function getRandomUpper() { 59 | return String.fromCharCode(Math.floor(Math.random() * 26) + 65); 60 | } 61 | function getRandomNumber() { 62 | return String.fromCharCode(Math.floor(secureMathRandom() * 10) + 48); 63 | } 64 | function getRandomSymbol() { 65 | const symbols = '~!@#$%^&*()_+{}":?><;.,'; 66 | return symbols[Math.floor(Math.random() * symbols.length)]; 67 | } 68 | 69 | // Selecting all the DOM Elements that are necessary --> 70 | 71 | // The Viewbox where the result will be shown 72 | const resultEl = document.getElementById("result"); 73 | // The input slider, will use to change the length of the password 74 | const lengthEl = document.getElementById("slider"); 75 | 76 | // Checkboxes representing the options that is responsible to create differnt type of password based on user 77 | const uppercaseEl = document.getElementById("uppercase"); 78 | const lowercaseEl = document.getElementById("lowercase"); 79 | const numberEl = document.getElementById("number"); 80 | const symbolEl = document.getElementById("symbol"); 81 | 82 | // Button to generate the password 83 | const generateBtn = document.getElementById("generate"); 84 | // Button to copy the text 85 | const copyBtn = document.getElementById("copy-btn"); 86 | // Result viewbox container 87 | const resultContainer = document.querySelector(".result"); 88 | // Text info showed after generate button is clicked 89 | const copyInfo = document.querySelector(".result__info.right"); 90 | // Text appear after copy button is clicked 91 | const copiedInfo = document.querySelector(".result__info.left"); 92 | 93 | // if this variable is trye only then the copyBtn will appear, i.e. when the user first click generate the copyBth will interact. 94 | let generatedPassword = false; 95 | 96 | // Update Css Props of the COPY button 97 | // Getting the bounds of the result viewbox container 98 | let resultContainerBound = { 99 | left: resultContainer.getBoundingClientRect().left, 100 | top: resultContainer.getBoundingClientRect().top, 101 | }; 102 | // This will update the position of the copy button based on mouse Position 103 | resultContainer.addEventListener("mousemove", e => { 104 | resultContainerBound = { 105 | left: resultContainer.getBoundingClientRect().left, 106 | top: resultContainer.getBoundingClientRect().top, 107 | }; 108 | if(generatedPassword){ 109 | copyBtn.style.opacity = '1'; 110 | copyBtn.style.pointerEvents = 'all'; 111 | copyBtn.style.setProperty("--x", `${e.x - resultContainerBound.left}px`); 112 | copyBtn.style.setProperty("--y", `${e.y - resultContainerBound.top}px`); 113 | }else{ 114 | copyBtn.style.opacity = '0'; 115 | copyBtn.style.pointerEvents = 'none'; 116 | } 117 | }); 118 | window.addEventListener("resize", e => { 119 | resultContainerBound = { 120 | left: resultContainer.getBoundingClientRect().left, 121 | top: resultContainer.getBoundingClientRect().top, 122 | }; 123 | }); 124 | 125 | // Copy Password in clipboard 126 | copyBtn.addEventListener("click", () => { 127 | const textarea = document.createElement("textarea"); 128 | const password = resultEl.innerText; 129 | if (!password || password == "CLICK GENERATE") { 130 | return; 131 | } 132 | textarea.value = password; 133 | document.body.appendChild(textarea); 134 | textarea.select(); 135 | document.execCommand("copy"); 136 | textarea.remove(); 137 | 138 | copyInfo.style.transform = "translateY(200%)"; 139 | copyInfo.style.opacity = "0"; 140 | copiedInfo.style.transform = "translateY(0%)"; 141 | copiedInfo.style.opacity = "0.75"; 142 | }); 143 | 144 | // When Generate is clicked Password id generated. 145 | generateBtn.addEventListener("click", () => { 146 | const length = +lengthEl.value; 147 | const hasLower = lowercaseEl.checked; 148 | const hasUpper = uppercaseEl.checked; 149 | const hasNumber = numberEl.checked; 150 | const hasSymbol = symbolEl.checked; 151 | generatedPassword = true; 152 | resultEl.innerText = generatePassword(length, hasLower, hasUpper, hasNumber, hasSymbol); 153 | copyInfo.style.transform = "translateY(0%)"; 154 | copyInfo.style.opacity = "0.75"; 155 | copiedInfo.style.transform = "translateY(200%)"; 156 | copiedInfo.style.opacity = "0"; 157 | }); 158 | 159 | // Function responsible to generate password and then returning it. 160 | function generatePassword(length, lower, upper, number, symbol) { 161 | let generatedPassword = ""; 162 | const typesCount = lower + upper + number + symbol; 163 | const typesArr = [{ lower }, { upper }, { number }, { symbol }].filter(item => Object.values(item)[0]); 164 | if (typesCount === 0) { 165 | return ""; 166 | } 167 | for (let i = 0; i < length; i++) { 168 | typesArr.forEach(type => { 169 | const funcName = Object.keys(type)[0]; 170 | generatedPassword += randomFunc[funcName](); 171 | }); 172 | } 173 | return generatedPassword.slice(0, length); 174 | } 175 | 176 | // function that handles the checkboxes state, so at least one needs to be selected. The last checkbox will be disabled. 177 | function disableOnlyCheckbox(){ 178 | let totalChecked = [uppercaseEl, lowercaseEl, numberEl, symbolEl].filter(el => el.checked) 179 | totalChecked.forEach(el => { 180 | if(totalChecked.length == 1){ 181 | el.disabled = true; 182 | }else{ 183 | el.disabled = false; 184 | } 185 | }) 186 | } 187 | 188 | [uppercaseEl, lowercaseEl, numberEl, symbolEl].forEach(el => { 189 | el.addEventListener('click', () => { 190 | disableOnlyCheckbox() 191 | }) 192 | }) 193 | --------------------------------------------------------------------------------