How do I merge these two bits of javascript? - javascript

I'm putting together a Flask web app as a final project for a course, and I'm struggling to fix some JavaScript for the site's registration form.
I have two independent bits of code, one from Bootstrap to validate form completeness:
<script>
(function()
{
'use strict';
window.addEventListener('load', function()
{
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form)
{
form.addEventListener('submit', function(event)
{
if (form.checkValidity() === false)
{
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
</script>
and one that I customized to check that the user is registering a unique username. If the username is not unique, it populates an innerHTML error to a "user_result" div tag beneath the username form field:
<script>
// set input value to form entry for username
let input = document.getElementById('user');
// on key up, run check
input.onkeyup = function()
{
// query to check username against database
$.get('/check?username=' + input.value, function(data)
{
// if check query returns False, username is NOT available
if (!data)
{
// put notification text into result tag above
document.getElementById('user_result').innerHTML = 'Username unavailable.';
// prevent form submission via register button
document.getElementById('register').addEventListener("click", function(event)
{
event.preventDefault();
});
}
// if check query returns True, username is available
if (data)
{
// no notification text required
document.getElementById('user_result').innerHTML = '';
// allow form submission by unbinding event handler
document.getElementById('register').addEventListener("click", function(event)
{
event.unbind();
});
}
});
};
</script>
Individually, each seems to work okay, but:
I can't seem to put both scripts in the same HTML doc without unexpected behavior (e.g. the form won't submit, but no error messages show, or the form submits despite a bad username.)
I'd really like for the "Username unavailable." message to display in the same style of the "invalid-feedback" class used for the Bootstrap form validation.
I'd even be fine checking for the username availability upon submit (see below attempt) instead of upon keyup, but I'd ideally check username validity before form submission.
Here is one of my attempts to stitch the code pieces together. The result here unfortunately is that the Bootstrap validation works, but the username check is ignored (I can submit the form with a bad username and instead of the JS blocking the form submission, it goes through).
<script>
(function()
{
// set input value to form entry for username
let input = document.getElementById('user');
'use strict';
window.addEventListener('load', function()
{
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form)
{
form.addEventListener('submit', function(event)
{
if (form.checkValidity() === true)
{
(function()
{
$.get('/check?username=' + input.value, function(data)
{
// if check query returns False, username is NOT available
if (!data)
{
// put notification text into result tag above
document.getElementById('user_result').innerHTML = 'Username unavailable.';
// prevent form submission via register button
document.getElementById('register').addEventListener("click", function(event)
{
event.preventDefault();
event.stopPropagation();
});
}
// if check query returns True, username is available
if (data)
{
// no notification text required
document.getElementById('user_result').innerHTML = '';
// allow form submission by unbinding event handler
document.getElementById('register').addEventListener("click", function(event)
{
event.unbind();
event.stopPropogation();
});
}
});
});
}
if (form.checkValidity() === false)
{
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
</script>
Can someone help me understand where my thinking is wrong? Please let me know if it'd be helpful to see the HTML form or Flask code for the username check.

Related

Control statement for removing attributes and classes having opposite effect

I'm building a registration page and I want the button to be disabled until all of the inputs pass validation. Well I have all of the native validation logic done (missing values, pattern mismatch, etc...), but I wanted to implement a "username taken/available" piece of validation where the button still wouldn't be enabled until the username had valid inputs for all of their inputs AND supplied a desired username that was not already in use.
I have the server call and all of that all done, my only issue is the actual enabling/disabling of the button and assigning the border classes to the inputs. Here is my code for the response from the AJAX call:
ajax.onload = function() {
if (this.responseText === "taken") {
if (username.classList.contains("taken")) {
return;
} else {
username.classList.remove("successBorder");
username.classList.add("errorBorder");
username.classList.add("taken");
}
} else {
if (!username.checkValidity()) {
username.classList.remove("successBorder");
username.classList.add("errorBorder");
return;
} else {
username.classList.remove("errorBorder");
username.classList.add("successBorder");
username.classList.remove("taken");
}
}
}
And then here is the code for where the button is enabled/disabled that is called on the input event for every input element:
function validate() {
if (document.querySelector("form").checkValidity() && !(username.classList.contains("taken"))) {
registerButton.removeAttribute("disabled");
const ruleSpans = document.querySelectorAll("span[data-rule]");
for (span of ruleSpans) {
span.classList.add("hide");
}
for (input of inputs) {
input.classList.remove("errorBorder");
input.classList.add("successBorder");
}
return;
}
registerButton.setAttribute("disabled", "true");
if (this.checkValidity()) {
// Get rid of the error messages
this.classList.remove("errorBorder");
this.classList.add("successBorder");
const ruleSpans = document.getElementsByClassName(this.id);
for (span of ruleSpans) {
span.classList.add("hide");
}
return;
}
// Adding attention borders and error messages based upon what the issue is
this.classList.remove("successBorder");
this.classList.add("errorBorder");
const ruleSpans = document.getElementsByClassName(this.id);
for (span of ruleSpans) {
span.classList.add("hide");
switch (span.getAttribute("data-rule")) {
case "patternMismatch":
if (this.validity.patternMismatch) {
span.classList.remove("hide");
}
break;
case "valueMissing":
if (this.validity.valueMissing) {
span.classList.remove("hide");
}
break;
case "typeMismatch":
if (this.validity.typeMismatch) {
span.classList.remove("hide");
}
break;
}
}
}
And right now, the disabling/enabling works IF it's the first time on input for that element, but it is "behind" all of the times after the first time. (for example, if the username is taken, the register button is enabled, but if the username is taken, the register button is disabled, the exact opposite of what I want happening).
So I thought, instead of checking for it the correct way (the way I did it in the code !(username.classList.contains("taken"))), I would reverse the logic to look like this: username.classList.contains("taken"). And that works (even though it is logically wrong and incredibly hack-y), EXCEPT for the first time a taken username is had.
What am I doing logically wrong here?
I would suggest you to have a code structure like this
function serverValidation () {
//make the ajax call here to validate all server validation
//send the success callback handler to 'clientValidations'
}
function clientValidations(){
//validate other form elements that does not require a server request here
//Then submit the form through an ajax form submit
submitFormThroughAjax();
}
function submitFormThroughAjax() {
//submit the form through ajax.
}
function onSubmit(event) {
event.preventDefault();
serverValidation();
}
//Here onSubmit should be attached to the form submit handler.
Refer:below link to know how to submit a form through ajax.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
This example does all the validations only after the user submits but if you want the errors to be shown instantaneously as the user interacts you need to handle it through specific form element events.

Controlling the submission

I'm trying to stop the submit if an error exists and go through the submission if no error exist.
This is just a section of the code. Regex works correctly, also the error texts were showing up too. The thing is that now I'm trying to control the submit proccess and due to an error (console is not showing up anything) the error text is not showing up and the submission is just going through even if an input error exists.
There is a mistake that I cannot figure out (No jquery please)
var sub = document.querySelector("#register input[type='submit']");//the submit botton
var err_text_1 = "First name must be filled out!";
sub.onsubmit = function(){
if (first_name == null || first_name == "") {
err_holder_1.innerHTML = err_text_1;
return false;
}
else {
err_holder_1.style.display = "none";
}
}
To prevent submit add event in the function and return false like so:
sub.onsubmit = function (event) {
// Will prevent submit
event.preventDefault();
return false;
};
Also select the form you are submitting not the button itself. So:
var sub = document.getElementById('ActionForm');
Hope this helps.
You need to select the form like
var sub = document.querySelector("#register");//If register is your form id Not input[type='submit']

Alternative for keyup function

am working in a popup when we click login a popup opens with fields !!! i want to check username and password with database before login button fired.. used ajax with keyup function for password field!
but keyup is firing for every character typed in password field... but the requirement is after typing password field ajax should be called and result should be displayed... is there any alternative for keyup?
now am getting as "wrong password for every character typed" and after entring correct password it will login,... but i want to show error as wrong password when user completely enters password (if password is wrong)
<script type="text/javascript">
$(document).ready(function() {
$("#upwd").change(function()
//$('#upwd').on('input', function()
//$('#upwd').keyup(_.debounce(doSomething , 500), function() {
var upwd = $("#upwd").val();
var uemail = $("#uemail").val();
var msgbox = $("#status");
//alert(uemail);
//alert(upwd);
//setTimeout(function() {
//if($('#upwd').val() == upwd){
$.ajax({
type: "POST",
url: "checkl_login.php",
data: "uemail="+ uemail,
success: function(msg){
$("#status").ajaxComplete(function(event, request){
if(msg == 'OK') {
msgbox.html(msg);
//return false;
} else {
msgbox.html(msg);
}
});
}
});
return false;
});
});
</script>
error displayed in status id in span......
checkl_login.php code is aalso perfect.....
Try using .focusout() event as shown :-
$("#upwd").on("focusout",function(){
//..your code..
});
and in addition of these events ,use a login button also and check validations on the click of the button.
Use the change event instead of keyup.
IMHO it's better:
to use keyup (it allows to handle any keyboard changes. For example, removing the symbol by backspace)
to handle 'paste' (because user may copy/paste password but not type it)
to validate password if user does not press a key during some period of time (for example, within 1 second) - setTimeout and clearTimeout should help
to abort ajax request if user starts to type when ajax request is in progress
I.e. you may try something like the following:
$(document).ready( function() {
var ajax_h;
var delayMilliseconds = 1000; // i.e. = 1 second
var timeoutId;
function checkAuth() {
if (ajax_h) {
ajax_h.abort();
}
ajax_h = $.ajax(
// PUT YOUR CODE HERE
);
}
$("#upwd").on('keyup paste', function () {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(checkAuth, delayMilliseconds);
});
});

Javascript - how to correctly verify form data?

I have a form with a few text inputs and also with one file-type input, in which I attempt to verify, if the selected file is PDF. I am doing that this way:
$("#myform").bind("submit", function() {
var ext = $('#file_input').val().split('.').pop().toLowerCase();
if($.inArray(ext, ['pdf']) == -1) {
alert('ERROR!');
}
});
But in the part of code above is one lack - if all inputs except the file-input (lets sat the file is DOC) are valid (=> file-input is not valid) and I click on the SUBMIT button, then is displayed alert message ERROR!, but the form is sent.
How can I "stop" sending the form, if the file type is not valid?
Try this:
$("#myform").bind("submit", function(e) {
var ext = $('#file_input').val().split('.').pop().toLowerCase();
if($.inArray(ext, ['pdf']) == -1) {
e.preventDefault(); //Prevents the default action which is form submit
alert('ERROR!');
}
});
You can shorten the code by doing this:
if (!(/\.pdf$/i).test($('#file_input').val())) {
// not valid, do what you like here
// return false to prevent submit
return false;
The form is prevented from submitting by returning false; preventDefault on the form submit event is not working in IE 7/8, return false does the job.
In a jQuery callback function bound to an event you have two options.
You can pass a reference to the event to the anonymous function and call e.preventDefault():
$('#myform').bind('submit', function(e) {
e.preventDefault();
// Your code
});
e.preventDefault() prevents the default functionality (in this case, submitting the form).
Or you can return false to both prevent the default functionality and prevent the event from bubbling; the same as calling e.preventDefault(); e.stopPropagation().
You have 2 ways:
Keep your code as it is and add return false:
$("#myform").bind("submit", function() {
var ext = $('#file_input').val().split('.').pop().toLowerCase();
if($.inArray(ext, ['pdf']) == -1) {
alert('ERROR!');
return false;
}
});
change the function signature to accept the event and use the preventDefault():
$("#myform").bind("submit", function(e) {
var ext = $('#file_input').val().split('.').pop().toLowerCase();
if($.inArray(ext, ['pdf']) == -1) {
alert('ERROR!');
e.preventDefault();
}
});

Display a warning with jQuery

I'm doing some jQuery form validation and I came up with an issue. I have the following code so far:
// catch any form submission
$('form').submit(function () {
'use strict';
// if the browser doesn't support HTML5's required attribute
if (!Modernizr.input.required) {
// catch any field that should be required
$(this).find('input[required]').each(function () {
// if is empty
if ($(this).val() === '') {
// create a span that contains a warning to the user
var requiredFieldWarning = document.createElement('span');
requiredFieldWarning.text = 'This field is required.';
// display the span next to the current field
}
});
}
});
I'm trying to "attach" or display a span next to any input of the submitted form that doesn't validate, but I don't know how to. I want to do this unobtrusively, that's why I create the said span inside JavaScript.
Also, how can I prevent the form from being submitted if any of the fields of the submitted form doesn't validate?
why reinvent the wheel? you should use the jquery form validation plugin..
edit: added code to prevent submition of invalid form.
to answer your question:
$('form').submit(function (e) {
'use strict';
var valid = true;
var $form = $(this);
$form.find("span.error").remove();
// if the browser doesn't support HTML5's required attribute
if (!Modernizr.input.required) {
// catch any field that should be required
$form.find(':input[required]').each(function () {
// if is empty
var $this = $(this);
if ($.trim($this.val()) === '') {
// create a span that contains a warning to the user
$this.after("<span class='error'>This field is required.</span>");
valid = false;
}
});
}
if(!valid){
e.preventDefault();
}
});
here is a shorter version:
$('form').submit(function (e) {
'use strict';
Modernizr.input.required ? e[$(this).find("span.error").remove().end()
.find(':input[required][value=""]')
.after("<span class='error'>This field is required.</span>")
.length ? 'preventDefault': 'isDefaultPrevented']() : null;
});
I am adding a span tag after the input. Before the form is revalidated it removes these spans and recreates only if needed. If any of these spans are added the form isn't submitted.
$('form').submit(function (event) {
'use strict';
$('.invalid-error', $(this)).remove();
// remove any old spans
var submit_form = true;
// form submits by default
// if the browser doesn't support HTML5's required attribute
if (!Modernizr.input.required) {
// catch any field that should be required
$(this).find('input[required]').each(function () {
// if is empty
if ($(this).val() === '') {
$(this).after('<span="invalid-error">This field is required.</span>');
// add span after input
submit_form = false;
}
});
}
if(!submit_form) event.preventDefault();
// stop form from submitting
});
jsFiddle ( http://jsfiddle.net/4KxzB/10/ )
Here is my working example, works as expected in chrome.
To stop the form from submitting, just return false;
<form>
<input type="text" required/>
<input type="submit" value="submit"/>
</form>
<script>
$('form').submit(function ()
{
'use strict';
// if the browser doesn't support HTML5's required attribute
if (!Modernizr.input.required)
{
var validInput = true;
// catch any field that should be required
$(this).find('input[required]').each(function ()
{
// if is empty
if ($(this).val() === '')
{
// create a span that contains a warning to the user
var requiredFieldWarning = document.createElement('span');
requiredFieldWarning.text = 'This field is required.';
// Cancels form submit
validInput = false;
}
});
return validInput;
}
});
</script>​
var flag = 0;
if ($(this).val() === '') {
flag = 1;
var warningblock = '<span class="warning">This field is required.</span>';
$(this).after(warningblock);
}
//end of each loop
if(flag){ //put this block out side the loop
return false; //form wont submit
}
return true;
CSS
.warning{
/**add styles for warning here***/
}

Categories

Resources