var constraints = {
  "user[username]": {
    presence: true,
    length: {
      minimum: 4,
      maximum: 20
    }
  },
  "user[email]": {
    presence: true,
    email: true
  },
  "user[password]": {
    presence: true,
    length: {
      minimum: 6,
      maximum: 128
    }
  },
  "user[password_confirmation]": {
    presence: true,
    equality: {
      attribute: "user[password]",
      message: "^The passwords do not match"
    }
  },
  "user[current_password]": {
    presence: true,
    length: {
      minimum: 6,
      maximum: 128
    }
  },
  "user[learning_goal]": {
    length: {
      minimum: 4,
      maximum: 100
    }
  },
};

document.addEventListener('turbolinks:load', function() {
  var forms = document.querySelectorAll('.form');
  if (!forms) return;

  forms.forEach(function(form) {
    var inputs = form.querySelectorAll('.form__element');
    
    inputs.forEach(function(item) {
      item.addEventListener("change", function(ev) {
        var errors = validate(form, constraints, { fullMessages: false }) || {};
        showErrorsForInput(this, errors[this.name]);
      });
    });
  });
});

function showErrorsForInput(input, errors) {
  var inputParent = input.parentNode;
  var errorWrapper = findErrorWrapper(input) || createErrorWrapper(input, inputParent);
  var errorDiv = findErrorDiv(input) || createErrorDiv(input, inputParent);

  if (!errors) {
    errorWrapper.parentNode.insertBefore(input, errorWrapper);
    errorWrapper.parentNode.removeChild(errorWrapper);
    errorDiv.parentNode.removeChild(errorDiv);
    return;
  }

  errorWrapper.classList.add('field_with_errors');
  errorDiv.innerHTML = errors;
}

function findErrorWrapper(input) {
  if (input.parentNode.classList.contains('field_with_errors')) {
    return input.parentNode;
  } else {
    return null;
  }
}

function createErrorWrapper(input, inputParent) {
  var newDiv = document.createElement('div');
  inputParent.appendChild(newDiv);
  newDiv.appendChild(input);
  return newDiv;
}

function findErrorDiv(input) {
  return document.querySelector("." + input.id);
}

function createErrorDiv(input, inputParent) {
  var divName = document.createElement('div');
  divName.classList.add('form__error-message', 'push-down', input.id);
  inputParent.parentNode.insertBefore(divName, inputParent.nextSibling);
  return divName;
}

@@ -35,36 +35,16 @@
 me%5D%22: %7B%0A
-    presence: true,%0A
     leng
@@ -41,32 +41,32 @@
 %7B%0A    length: %7B%0A
+
       minimum: 4
@@ -115,36 +115,16 @@
 il%5D%22: %7B%0A
-    presence: true,%0A
     emai
@@ -158,36 +158,16 @@
 rd%5D%22: %7B%0A
-    presence: true,%0A
     leng
@@ -255,36 +255,16 @@
 on%5D%22: %7B%0A
-    presence: true,%0A
     equa
@@ -396,28 +396,8 @@
 : %7B%0A
-    presence: true,%0A
     
@@ -677,17 +677,19 @@
 return;%0A
+  
 %0A
-
   forms.
@@ -709,24 +709,178 @@
 ion(form) %7B%0A
+    %0A    form.addEventListener(%22submit%22, function(ev) %7B%0A      ev.preventDefault();%0A      handleFormSubmit(form);%0A      ev.stopPropagation();%0A    %7D)%0A  %0A  %0A
     var inpu
@@ -1181,13 +1181,397 @@
 %7D);%0A
-
 %7D);%0A%0A
+function handleFormSubmit(form) %7B%0A  var formErrors = validate(form, constraints, %7B fullMessages: false %7D);%0A  if (!formErrors) %7B%0A    form.submit();%0A  %7D%0A  showErrors(form, formErrors %7C%7C %7B%7D);%0A%7D%0A%0Afunction showErrors(form, errors) %7B%0A  var formInputs = form.querySelectorAll('.form__element');%0A  formInputs.forEach(function(item) %7B%0A    showErrorsForInput(item, errors%5Bitem.name%5D);%0A  %7D);%0A%7D%0A%0A
 func

stop form submit when input invalid