0

I have a simple password validation. Two input fields with icons clicking on which the user can see the entered password. The code works good. But I write two similar duplicate codes for two similar inputs. And cannot manage to shorten the code so that the event can be added once, and works for two inputs (but not simultaneously). Here is the JS code.

const password = document.getElementById('pass');
const repeatPass = document.getElementById('repeat_pass');

function validatePassword() {
    const icon = document.getElementById('icon1');
    const icon2 = document.getElementById('icon2');
    icon.addEventListener('click', () => {
        if (password.getAttribute('type') === 'password') {
            password.setAttribute('type', 'text');
            icon.classList.add('fa-eye-slash');
            icon.classList.remove('fa-eye');
        } else {
            icon.classList.remove('fa-eye-slash');
            icon.classList.add('fa-eye');
            password.setAttribute('type', 'password');
        }
    });

    icon2.addEventListener('click', () => {
        if (repeatPass.getAttribute('type') === 'password') {
            repeatPass.setAttribute('type', 'text');
            icon2.classList.add('fa-eye-slash');
            icon2.classList.remove('fa-eye');
        } else {
            icon2.classList.remove('fa-eye-slash');
            icon2.classList.add('fa-eye');
            repeatPass.setAttribute('type', 'password');
        }
    });

    const submit = document.querySelector('.password-form')
    const errorText = document.createElement('span');
    submit.addEventListener('submit', () => {
            if (password.value !== repeatPass.value) {
                repeatPass.after(errorText);
                errorText.innerText = 'Password does not match.';
                errorText.style.color = 'red';
            } else {
                password.value = "";
                repeatPass.value = "";
                alert('You are welcome');
            }
        }
    );
}

validatePassword();
2
  • 1
    Put your event handlers into a a function that contains the repeated code. Commented Dec 4, 2020 at 18:33
  • Why not simply put the validation logic in a extra function? Commented Dec 4, 2020 at 18:33

3 Answers 3

2

You could do something like this:

function myFunction(target, icon) { // create a function that accepts arguments
  const element = document.getElementById(target) // query whatever element you pass to it.
  if (element.getAttribute('type') === 'password') {
    element.setAttribute('type', 'text');
    icon.classList.add('fa-eye-slash');
    icon.classList.remove('fa-eye');
  } else {
    icon.classList.remove('fa-eye-slash');
    icon.classList.add('fa-eye');
    element.setAttribute('type', 'password');
  }
}

icon.addEventListener('click', () => myFunction('pass', icon)); // add the event listeners wrapped in anonymous function so it's not called immediately
icon2.addEventListener('click', () => myFunction('repeat_pass', icon2));
Sign up to request clarification or add additional context in comments.

3 Comments

They have two different icons, one for each password. In myFunction, the same icon is referenced for both passwords. That being said, this is the right general idea.
Updated by passing icon element as a second parameter.
Looks good. Just note, the var that they for the 1st icon is icon, not icon1.
0

You can create a function that accepts the different bits as arguments. Ex:

const password = document.getElementById('pass');
const repeatPass = document.getElementById('repeat_pass');

function clickShowHide(passwd, iconElem) {
    if (passwd.getAttribute('type') === 'password') {
        passwd.setAttribute('type', 'text');
        iconElem.classList.add('fa-eye-slash');
        iconElem.classList.remove('fa-eye');
    } else {
        iconElem.classList.remove('fa-eye-slash');
        iconElem.classList.add('fa-eye');
        passwd.setAttribute('type', 'password');
    }
}
function validatePassword() {
    const icon = document.getElementById('icon1');
    const icon2 = document.getElementById('icon2');
    
    icon.addEventListener('click', () => clickShowHide(password, icon));

    icon2.addEventListener('click', () => clickShowHide(repeatPass, icon2));

    const submit = document.querySelector('.password-form')
    const errorText = document.createElement('span');
    submit.addEventListener('submit', () => {
            if (password.value !== repeatPass.value) {
                repeatPass.after(errorText);
                errorText.innerText = 'Password does not match.';
                errorText.style.color = 'red';
            } else {
                password.value = "";
                repeatPass.value = "";
                alert('You are welcome');
            }
        }
    );
}

validatePassword();

Comments

0

You can refactor it in functional way, using js closures

The full code will be like this:

const password = document.getElementById('pass');
const repeatPass = document.getElementById('repeat_pass');

const togglePassword = (passwordId) => (iconId) => () => {
  const password = document.getElementById(passwordId);
  const icon = document.getElementById(iconId);

  if (password.getAttribute('type') === 'password') {
    password.setAttribute('type', 'text');
    icon.classList.add('fa-eye-slash');
    icon.classList.remove('fa-eye');
  } else {
    icon.classList.remove('fa-eye-slash');
    icon.classList.add('fa-eye');
    password.setAttribute('type', 'password');
  }
}

function validatePassword() {
    const icon = document.getElementById('icon1');
    const icon2 = document.getElementById('icon2');

    icon.addEventListener('click', togglePassword('pass')('icon1'));
    icon2.addEventListener('click', togglePassword('repeat_pass')('icon2'));


    const submit = document.querySelector('.password-form')
    const errorText = document.createElement('span');
    submit.addEventListener('submit', () => {
            if (password.value !== repeatPass.value) {
                repeatPass.after(errorText);
                errorText.innerText = 'Password does not match.';
                errorText.style.color = 'red';
            } else {
                password.value = "";
                repeatPass.value = "";
                alert('You are welcome');
            }
        }
    );
}

validatePassword();

1 Comment

You dropped a ' around icon2 :P

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.