0

I want to prevent completely users to modify the values of the number input form in any way that is not using the arrows in the form. Basically I have this:

const pwEl = document.getElementById("pw");
const copyEl = document.getElementById("copy");
const lenEl = document.getElementById("len");
const upperEl = document.getElementById("upper");
const numberEl = document.getElementById("number");
const symbolEl = document.getElementById("symbol");
const generateEl = document.getElementById("generate");
const footerEl = document.getElementById("footer");


const lowerLetters = "abcdefghijklmnopqrstuvwxyz"
const upperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const numbers = "1234567890"
const specialCharacters = "|@#~€!$%&/()=?¿"


function randomUpper() {
    return upperLetters[Math.floor(Math.random()*upperLetters.length)];
}

function randomNumbers() {
    return numbers[Math.floor(Math.random()*numbers.length)];
}

function randomSpecial() {
    return specialCharacters[Math.floor(Math.random()*specialCharacters.length)];
}

function randomLower() {
    return lowerLetters[Math.floor(Math.random()*lowerLetters.length)];
}


function generateChunk() {
    const xs = [];
    xs.push(randomLower());
    if (upperEl.checked) {
        xs.push(randomUpper());
    }
    if (numberEl.checked) {
        xs.push(randomNumbers());
    }
    if (symbolEl.checked) {
        xs.push(randomSpecial());
    }
    return xs[Math.floor(Math.random()*xs.length)];
}


function generatePassword() {
    const len = lenEl.value;
    let password = "";
    for (let i = 0; i < len; i++) {
        password += generateChunk();
    }
    pwEl.innerText = password;
}

function copy() {
    var textArea = document.createElement("textarea");
    textArea.value = pwEl.textContent;
    document.body.appendChild(textArea);
    textArea.select();
    document.execCommand("Copy");
    textArea.remove();

    //adding class to transition 
    footerEl.innerText = "Succesfully copied to clipboard!";
    footerEl.classList.add("footer-active");
    setTimeout(() => {
        footerEl.classList.remove("footer-active");
    }, 1000)
    setTimeout(() => {
        footerEl.innerText = "";
    }, 1200);
}

generateEl.addEventListener("click", generatePassword);

copyEl.addEventListener("click", copy);
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@500&display=swap');

* {
    box-sizing: border-box;
}

body{
    background-color:#37505c;
    color: #FFEAD0;
    font-family: 'Raleway', sans-serif;
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
}

.pw-container{
    background-color: #113537;
    width:500px;
    box-shadow: 5px 10px 8px rgba(0,0,0,0.2);
    z-index:2;

}

.pw {
    background-color:#37505c;
    height: 70px;
    width:100%;
    position: relative;
    align-items: center;
    font-size: 2rem;
    padding: 1rem;
    text-align: center;
}

.pw button{
    font-family: inherit;
    position: absolute;
    top: 0;
    right: 0;
    transform: translate(0, -20%);
    background-color: #FFFFFF;
    border: none;
    color: #000000;
    padding: 0.25rem;
    opacity:0;
    transition: opacity 0.2s ease, transform 0.2s ease;
    cursor: pointer;
}

.pw:hover button {
    opacity: 1;
    transform: translate(0, -90%)
}

.pw-header {
    padding: 1rem;
}

.pw-body {
    padding: 0 1rem 1rem;
}

.form-control {
    display:flex;
    justify-content: space-between;
    margin: 0.5rem;
}

.generate {
    background-color: #FFFFFF;
    display:block;
    border: none;
    font-size: 1rem;
    padding : 0.5rem;
    width: 100%;
    margin-top: 2rem;
}


.footer {
    position: absolute;
    top: 1;
    bottom: 0;
    font-size: 2rem;
    width:100%;
    background-color:#113537;
    text-align: center;
    padding: 2rem;
    opacity:0;
    transition: opacity 0.2s ease;
    z-index: 1;

}

.footer-active {
    opacity: 1;
    transform: translate(0, 0%);
    z-index: 1;
    
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Password Generator</title>
    <link rel="stylesheet" href="styles.css">
    <script src="script.js" defer></script>
</head>
<body>

    <div class="pw-container">
        <div class="pw-header">
            <div class="pw">
                <span id="pw">1234</span>
                <button id="copy">Copy to clipboard</button>
            </div>
        </div>

        <div class="pw-body">
            <div class="form-control">
                <label for="len">Length</label>
                <input id="len" onKeyDown="return false" type="number" min="5" max="20" value="7">
            </div>

            <div class="form-control">
                <label for="upper">Uppercase</label>
                <input id="upper" type="checkbox">
            </div>

            <div class="form-control">
                <label for="number">Numbers</label>
                <input id="number" type="checkbox">
            </div>

            <div class="form-control">
                <label for="symbol">Symbols</label>
                <input id="symbol" type="checkbox">
            </div>

            <button class="generate" id="generate">
                Generate Password
            </button>
        </div>
    </div>

    <div id="footer" class="footer">
    </div>
    
</body>
</html>

Note that in the input, I added onKeyDown="return false", an answer in other post like this one. However, this is not going to prevent the user from doing a paste of any value he wants, nor moving a value with the mouse into the field. Is there any way to prevent it?

FluffyKitten
  • 13,824
  • 10
  • 39
  • 52
Norhther
  • 545
  • 3
  • 15
  • 35

2 Answers2

1

By using event listeners, if the user focuses on the input then blur:

jQuery:

$("input").on("focus", function() {
    $(this).blur();
});

Vanilla:

const input = document.querySelector("input#len");

input.addEventListener("focus", function() {
    input.blur();
});
Maverick Fabroa
  • 1,105
  • 1
  • 9
  • 15
1

You can easily block any events you want with event handlers like this - it takes a list of events and adds an event handler for each to block it. You can add as many or few events as you need - see a list of Events here:

"keypress paste dragstart drop cut".split(" ").forEach(function(e){
    lenEl.addEventListener(e, function(e){
        e.preventDefault();
        return false;
    });
});

Working Example - Accessible Version: Allows tab and arrow keys

const pwEl = document.getElementById("pw");
const copyEl = document.getElementById("copy");
const lenEl = document.getElementById("len");
const upperEl = document.getElementById("upper");
const numberEl = document.getElementById("number");
const symbolEl = document.getElementById("symbol");
const generateEl = document.getElementById("generate");
const footerEl = document.getElementById("footer");


const lowerLetters = "abcdefghijklmnopqrstuvwxyz"
const upperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const numbers = "1234567890"
const specialCharacters = "|@#~€!$%&/()=?¿"

"keypress paste dragstart drop cut".split(" ").forEach(function(e){
    lenEl.addEventListener(e, function(e){
        e.preventDefault();
        return false;
    });
});

function randomUpper() {
    return upperLetters[Math.floor(Math.random()*upperLetters.length)];
}

function randomNumbers() {
    return numbers[Math.floor(Math.random()*numbers.length)];
}

function randomSpecial() {
    return specialCharacters[Math.floor(Math.random()*specialCharacters.length)];
}

function randomLower() {
    return lowerLetters[Math.floor(Math.random()*lowerLetters.length)];
}


function generateChunk() {
    const xs = [];
    xs.push(randomLower());
    if (upperEl.checked) {
        xs.push(randomUpper());
    }
    if (numberEl.checked) {
        xs.push(randomNumbers());
    }
    if (symbolEl.checked) {
        xs.push(randomSpecial());
    }
    return xs[Math.floor(Math.random()*xs.length)];
}


function generatePassword() {
    const len = lenEl.value;
    let password = "";
    for (let i = 0; i < len; i++) {
        password += generateChunk();
    }
    pwEl.innerText = password;
}

function copy() {
    var textArea = document.createElement("textarea");
    textArea.value = pwEl.textContent;
    document.body.appendChild(textArea);
    textArea.select();
    document.execCommand("Copy");
    textArea.remove();

    //adding class to transition 
    footerEl.innerText = "Succesfully copied to clipboard!";
    footerEl.classList.add("footer-active");
    setTimeout(() => {
        footerEl.classList.remove("footer-active");
    }, 1000)
    setTimeout(() => {
        footerEl.innerText = "";
    }, 1200);
}

generateEl.addEventListener("click", generatePassword);

copyEl.addEventListener("click", copy);
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@500&display=swap');

* {
    box-sizing: border-box;
}

body{
    background-color:#37505c;
    color: #FFEAD0;
    font-family: 'Raleway', sans-serif;
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
}

.pw-container{
    background-color: #113537;
    width:500px;
    box-shadow: 5px 10px 8px rgba(0,0,0,0.2);
    z-index:2;

}

.pw {
    background-color:#37505c;
    height: 70px;
    width:100%;
    position: relative;
    align-items: center;
    font-size: 2rem;
    padding: 1rem;
    text-align: center;
}

.pw button{
    font-family: inherit;
    position: absolute;
    top: 0;
    right: 0;
    transform: translate(0, -20%);
    background-color: #FFFFFF;
    border: none;
    color: #000000;
    padding: 0.25rem;
    opacity:0;
    transition: opacity 0.2s ease, transform 0.2s ease;
    cursor: pointer;
}

.pw:hover button {
    opacity: 1;
    transform: translate(0, -90%)
}

.pw-header {
    padding: 1rem;
}

.pw-body {
    padding: 0 1rem 1rem;
}

.form-control {
    display:flex;
    justify-content: space-between;
    margin: 0.5rem;
}

.generate {
    background-color: #FFFFFF;
    display:block;
    border: none;
    font-size: 1rem;
    padding : 0.5rem;
    width: 100%;
    margin-top: 2rem;
}


.footer {
    position: absolute;
    top: 1;
    bottom: 0;
    font-size: 2rem;
    width:100%;
    background-color:#113537;
    text-align: center;
    padding: 2rem;
    opacity:0;
    transition: opacity 0.2s ease;
    z-index: 1;

}

.footer-active {
    opacity: 1;
    transform: translate(0, 0%);
    z-index: 1;
    
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Password Generator</title>
    <link rel="stylesheet" href="styles.css">
    <script src="script.js" defer></script>
</head>
<body>

    <div class="pw-container">
        <div class="pw-header">
            <div class="pw">
                <span id="pw">1234</span>
                <button id="copy">Copy to clipboard</button>
            </div>
        </div>

        <div class="pw-body">
            <div class="form-control">
                <label for="len">Length</label>
                <input id="len" type="number" min="5" max="20" value="7">
            </div>

            <div class="form-control">
                <label for="upper">Uppercase</label>
                <input id="upper" type="checkbox">
            </div>

            <div class="form-control">
                <label for="number">Numbers</label>
                <input id="number" type="checkbox">
            </div>

            <div class="form-control">
                <label for="symbol">Symbols</label>
                <input id="symbol" type="checkbox">
            </div>

            <button class="generate" id="generate">
                Generate Password
            </button>
        </div>
    </div>

    <div id="footer" class="footer">
    </div>
    
</body>
</html>

Blocking ALL Key Presses

Note that it is not recommended to prevent all keyDown/keyUp events, for accesibility reasons - it makes your form impossible to use without mouse/touch screen - not only are you unable to change the values, you get stuck inside that input forever and can't even tab out of it! \

Therefore I use keypress instead of keydown above, as keypress allows for control keys to work but if you really need to, you can use keydown instead.

Working Example Blocking ALL Key Presses (inaccessible for visually impaired users)

const pwEl = document.getElementById("pw");
const copyEl = document.getElementById("copy");
const lenEl = document.getElementById("len");
const upperEl = document.getElementById("upper");
const numberEl = document.getElementById("number");
const symbolEl = document.getElementById("symbol");
const generateEl = document.getElementById("generate");
const footerEl = document.getElementById("footer");


const lowerLetters = "abcdefghijklmnopqrstuvwxyz"
const upperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const numbers = "1234567890"
const specialCharacters = "|@#~€!$%&/()=?¿"

"keydown paste dragstart drop cut".split(" ").forEach(function(e){
    lenEl.addEventListener(e, function(e){
        e.preventDefault();
        return false;
    });
});

function randomUpper() {
    return upperLetters[Math.floor(Math.random()*upperLetters.length)];
}

function randomNumbers() {
    return numbers[Math.floor(Math.random()*numbers.length)];
}

function randomSpecial() {
    return specialCharacters[Math.floor(Math.random()*specialCharacters.length)];
}

function randomLower() {
    return lowerLetters[Math.floor(Math.random()*lowerLetters.length)];
}


function generateChunk() {
    const xs = [];
    xs.push(randomLower());
    if (upperEl.checked) {
        xs.push(randomUpper());
    }
    if (numberEl.checked) {
        xs.push(randomNumbers());
    }
    if (symbolEl.checked) {
        xs.push(randomSpecial());
    }
    return xs[Math.floor(Math.random()*xs.length)];
}


function generatePassword() {
    const len = lenEl.value;
    let password = "";
    for (let i = 0; i < len; i++) {
        password += generateChunk();
    }
    pwEl.innerText = password;
}

function copy() {
    var textArea = document.createElement("textarea");
    textArea.value = pwEl.textContent;
    document.body.appendChild(textArea);
    textArea.select();
    document.execCommand("Copy");
    textArea.remove();

    //adding class to transition 
    footerEl.innerText = "Succesfully copied to clipboard!";
    footerEl.classList.add("footer-active");
    setTimeout(() => {
        footerEl.classList.remove("footer-active");
    }, 1000)
    setTimeout(() => {
        footerEl.innerText = "";
    }, 1200);
}

generateEl.addEventListener("click", generatePassword);

copyEl.addEventListener("click", copy);
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@500&display=swap');

* {
    box-sizing: border-box;
}

body{
    background-color:#37505c;
    color: #FFEAD0;
    font-family: 'Raleway', sans-serif;
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
}

.pw-container{
    background-color: #113537;
    width:500px;
    box-shadow: 5px 10px 8px rgba(0,0,0,0.2);
    z-index:2;

}

.pw {
    background-color:#37505c;
    height: 70px;
    width:100%;
    position: relative;
    align-items: center;
    font-size: 2rem;
    padding: 1rem;
    text-align: center;
}

.pw button{
    font-family: inherit;
    position: absolute;
    top: 0;
    right: 0;
    transform: translate(0, -20%);
    background-color: #FFFFFF;
    border: none;
    color: #000000;
    padding: 0.25rem;
    opacity:0;
    transition: opacity 0.2s ease, transform 0.2s ease;
    cursor: pointer;
}

.pw:hover button {
    opacity: 1;
    transform: translate(0, -90%)
}

.pw-header {
    padding: 1rem;
}

.pw-body {
    padding: 0 1rem 1rem;
}

.form-control {
    display:flex;
    justify-content: space-between;
    margin: 0.5rem;
}

.generate {
    background-color: #FFFFFF;
    display:block;
    border: none;
    font-size: 1rem;
    padding : 0.5rem;
    width: 100%;
    margin-top: 2rem;
}


.footer {
    position: absolute;
    top: 1;
    bottom: 0;
    font-size: 2rem;
    width:100%;
    background-color:#113537;
    text-align: center;
    padding: 2rem;
    opacity:0;
    transition: opacity 0.2s ease;
    z-index: 1;

}

.footer-active {
    opacity: 1;
    transform: translate(0, 0%);
    z-index: 1;
    
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Password Generator</title>
    <link rel="stylesheet" href="styles.css">
    <script src="script.js" defer></script>
</head>
<body>

    <div class="pw-container">
        <div class="pw-header">
            <div class="pw">
                <span id="pw">1234</span>
                <button id="copy">Copy to clipboard</button>
            </div>
        </div>

        <div class="pw-body">
            <div class="form-control">
                <label for="len">Length</label>
                <input id="len" type="number" min="5" max="20" value="7">
            </div>

            <div class="form-control">
                <label for="upper">Uppercase</label>
                <input id="upper" type="checkbox">
            </div>

            <div class="form-control">
                <label for="number">Numbers</label>
                <input id="number" type="checkbox">
            </div>

            <div class="form-control">
                <label for="symbol">Symbols</label>
                <input id="symbol" type="checkbox">
            </div>

            <button class="generate" id="generate">
                Generate Password
            </button>
        </div>
    </div>

    <div id="footer" class="footer">
    </div>
    
</body>
</html>

Note, you no longer need the onkeydown or other event handlers on the input itself in either of these examples

FluffyKitten
  • 13,824
  • 10
  • 39
  • 52
  • This works with the paste, but it doesn't prevent for the user to move a value inside the field with the mouse – Norhther Sep 20 '20 at 16:17
  • @Norhther We can add any number of events you want to block, I'd just caution blocking everything by default because it *will* affect accessibility for the visually impaired etc. I'll update my answer for this also, and I will suggest a way to prevent content being entered by keypress but still allowing control key presses - blocking all key presses means you're stuck in that input forever!! – FluffyKitten Sep 20 '20 at 16:34
  • Oh, I see. Works like a charm. Thanks. – Norhther Sep 20 '20 at 18:41