MaksimL
MaksimL

Reputation: 314

How to avoid duplicated code in password validation (JS)

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();

Upvotes: 0

Views: 236

Answers (3)

Montecamo
Montecamo

Reputation: 136

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();

Upvotes: 0

Matthew Moran
Matthew Moran

Reputation: 1497

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));

Upvotes: 2

John Paul R
John Paul R

Reputation: 752

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();

Upvotes: 0

Related Questions