Failed to stop alert fire twice using flag - javascript

Try to write a validation library but stuck on somewhere. How to alert only once although they are 2 validation layer?
var validation_event = {
mandatory: function(that) {
if (!$(that).val() && $(that).data('placeholder')) {
alert('Please fill in ' + $(that).data('placeholder') + '.');
return false;
}
},
email: function(that) {
var regex = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if ($(that).val() == '' || !regex.test($(that).val())) {
alert('Please make sure the ' + $(that).data('placeholder') + ' is valid.');
return false;
}
}
}
https://jsfiddle.net/wvzbq9h2/
Try to click submit, you will see there are 2 alert. Other than that things are working fine.

#XzenTorXz 's fiddle is correct answer i.e. https://jsfiddle.net/wvzbq9h2/3/
your mistake is that your validation is returning the false after alert, but you never use that value to stop the $.each. You need to stop $.each after first alert.

$(function() {
var options = ['mandatory', 'email'];
var validation_event = {
mandatory: function(that) {
if (!$(that).val() && $(that).data('placeholder')) {
alert('Please fill in ' + $(that).data('placeholder') + '.');
that.stopPropagation();
}
},
email: function(that) {
var regex = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if ($(that).val() == '' || !regex.test($(that).val())) {
alert('Please make sure the ' + $(that).data('placeholder') + ' is valid.');
that.stopPropagation();
}
}
}

If you want to have a single message:
You can use the return false to break out of the $.each. You also need to return true on a successfull validation: https://jsfiddle.net/wvzbq9h2/4/
If you want to have multiple message shown (if multiple validations fail) you need to collect your messages (returning them from validation) and alert them at the finish. See https://jsfiddle.net/wvzbq9h2/6/. You could also combine the 2 so that you only have 1 message per field, see: https://jsfiddle.net/wvzbq9h2/7/

Related

How can I conditionally allow or prevent submission execution?

The situation
I have a page in which I have multiple forms keeping track of the attendance and one progress_update.
On submit of the progress_update form I have got it so that ajax sends the attendance form submissions separately having used the preventdefault() method to stop the original submission, however I would like to on the condition that no errors were returned by the ajax methods allow the original submission that was originally prevented.
What I have so far:
The ajax function:
function send_attendance(name, lesson, form_id, i) {
var url = '/attendance/' + name + '/' + lesson
$('#error-' + i).hide('slow')
$('#error-' + i).html('')
$.ajax({
type: "POST",
url: url,
data: {
attended: $('#attended' + i).val(),
score: $('#score' + i).val(),
writing: $('#writing' + i).val(),
speaking: $('#speaking' + i).val()},
success: function(data) {
if (data.data.message == undefined) {
allow=false;
if (data.data.score[1] == undefined) {
var error_data = data.data.score[0]
} else {
var error_data = data.data.score[1]
}
$('#error-' + i).show('slow')
$('#error-' + i).html('<p style="color:red;">' + error_data + '</p>')
} else {
console.log(data.data.message) // display the returned data in the console.
}
}
});
}
The Intention:
The intention behind this ajax is to send the forms to a separate route for validation and then on success "receiving data.data.message == 'submitted'" pass to the next form in the loop, while on error set the allow variable to false and display the message in hopes to prevent the final form being submitted at the same time.
The call:
$('#update_form').submit(function (e) {
var allow = true;
for (var i = 0; i < studentcount ; i++) {
send_attendance(name=st[i], lesson=lesson, form_id='attendance-' + i, i=i)
}
if (allow == true){
} else {
e.preventDefault();
}
});
The Problem
In doing what I have done I have ended up with a situation of it either submits the ajax submitted forms and that is that preventing the submit form or it submits the form whether errors occured in the ajax that need to be displayed, now how do I get this to work in the way expected? I have tried the methods involved in these previous questions:
How to reenable event.preventDefault?
How to unbind a listener that is calling event.preventDefault() (using jQuery)?
which revolve around using bind and unbind but this doesn't seem to work as needed and results in a similar error.
Any advice would be greatly appreciated.
Edit:
I have adjusted the code based on the comment below to reflect, however it still seems to be evaluating the allow before the ajax have completed. either that or the ajax function isn't changing the allow variable which is set in the submit() call how could i get this to change the allow and evaluate it after the ajax calls are complete?
The Ajax call
function send_attendance(name, lesson, form_id, i) {
var url = '/attendance/' + name + '/' + lesson
$('#error-' + i).hide('slow')
$('#error-' + i).html('')
var form = $('#' + form_id)
$.ajax({
type: "POST",
url: url,
data: $('#'+ form_id).serialize(),
context: form,
success: function(data) {
console.log('done')
if (data.data.message == undefined) {
allow = false;
if (data.data.score[1] == undefined) {
var error_data = data.data.score[0]
} else {
var error_data = data.data.score[1]
}
$('#error-' + i).show('slow')
$('#error-' + i).html('<p style="color:red;">' + error_data + '</p>')
} else {
console.log(data.data.message) // display the returned data in the console.
}
}
});
The function is being called here:
$('#update_form').submit(function (e) {
e.preventDefault();
var allow = true;
var deferreds = [];
for (var i = 0; i < studentcount ; i++) {
deferreds.push(
send_attendance(st[i], lesson, 'attendance-' + i, i));
}
$.when(...deferreds).then(function() {
if (allow == true){
console.log('True')
} else {
console.log('False')
}
});
I also tried:
$('#update_form').submit(function (e) {
e.preventDefault();
var allow = true;
var deferreds = [];
for (var i = 0; i < studentcount ; i++) {
deferreds.push(
send_attendance(st[i], lesson, 'attendance-' + i, i));
}
$.when.apply(deferreds).done(function() {
if (allow == true){
console.log('True')
} else {
console.log('False')
}
});

Prevent sending data to DB/server if form validation is false (VueJS)

I want to stop sending information if form validation is false.
I have a button Save with two functions in it:
<span class="logInBTN" v-on:click="validationFields(); function2(model)">Save</span>
The form validation is being proccessed in validationFields():
validationFields() {
if (this.model.codePerson == '') {
document.getElementById('codePerson').style.borderColor = "red";
this.errors.push("Choose a type!\n");
falseValidation = true;
} else {
document.getElementById('codePerson').style.borderColor = "#CCCCCC";
}
if (falseValidation == true) {
alert("Form validation:\n" + this.errors.join(""));
}
}
So if it's not chosen a type from the input field, function2() must not continue.
Update1:
<script>
export default {
components: {
},
data(){
return {
errors: [];
},
},
methods: {
validationFields() {
this.errors = [];
var falseValidation = false;
if (this.model.codePerson == '') {
document.getElementById('codePerson').style.borderColor = "red";
this.errors.push("Choose a type!\n");
falseValidation = true;
} else {
document.getElementById('codePerson').style.borderColor = "#CCCCCC";
}
if (falseValidation == true) {
alert("Form validation:\n" + this.errors.join(""));
}
if(falseValidation == false){
this.createEori(eoriData);
}
}
createEori(eoriData) {
eoriData.state = '1';
eoriData.username = this.$session.get('username');
console.log("updateEori state: " + JSON.stringify(eoriData));
const url = this.$session.get('apiUrl') + 'registerEORI';
this.submit('post',
url,
eoriData
);
},
submit(requestType, url, submitData) {
this.$http[requestType](url, submitData)
.then(response => {
console.log('EORI saved!');
console.log('Response:' + response.data.type);
if("E" == response.data.type){
alert(response.data.errorDescription);
} else {
alert("Saved!");
}
})
.catch(error => {
console.log('EORI rejected!');
console.log('error:' + error);
});
},
},
}
</script>
createEORI is the function2
Update2
Now it works, but the data from the fields it's not send to the server. That's all fields from the page, some are datepickers or an ordinary input text field. Before the change in the browser console show this, if I write a name in the first field it will show up in c1_name etc:
{"state":"1","c1_form":"","c1_identNumber":"","c1_name":"","c1_shortName":"","c1_8_street":"","c1_8_pk":"","c1_8_name":"","c1_8_city":"","c1_8_codeCountry":"","c1_identNumber1":"","c3_name":"","c3_nameShort":"","c3_city":"","c3_codeCountry":"","c3_street":"","c3_pk":"","c3_phone":"","codePerson":"","codeActivity":"","c1_date":"","c5_date":"","c7_date":"","dateFrom":"","dateTo":"","c8_date":"","c1_numberVAT":"","c8_provider":"","c8_number":"","codeMU":"","agreed1":"","agreed2":"","username":"testuser"}
However, after the change the sent data or at least the seen data is only:
{"state":"1","username":"testuser"}
The log is from
console.log("updateEori state: " + JSON.stringify(eoriData));
from createEORI() function
I think it would be better practice to only call one function from the HTML. Something like this:
<span class="logInBTN" v-on:click="submit(model)">Save</span>
submit(model) {
if (this.validateForm(model) == true)
{
// submission process here (maybe call function2())
}
}
validateForm(model) {
if (this.model.codePerson == ''){
document.getElementById('codePerson').style.borderColor = "red";
this.errors.push("Choose a type!\n");
this.handleFalseValidation();
return false;
}
document.getElementById('codePerson').style.borderColor = "#CCCCCC";
return true;
}
handleFalseValidation() {
alert("Form validation:\n" + this.errors.join(""));
}
Ok I fixed the problems with sending the data.
It was my fault.
I will copy the Chris answer. That worked.
When you call this.createEori(eoriData);, eoriData is undefined. It doesn't exist. Use this.createEori(); instead, and in the createEori function, remove the parameter and add var eoriData = {}; as first line. (note this is very basic javascript, how functions and variables work, and completely unrelated to Vue or server requests)

Mousedown still submitting form, when it should not

hello i have a login validation form which uses a mix of jquery and ajax to do validations... if the values are ok the form should submit, if the values are not ok then the form should not submit... however in my case the form is submitting even when the values are incorrect ( i am using the mousedown function ) please see below my code..
<form method="post" name="loginform" action="models/login.php">
<input type="email" class="homepage" name="user_email2" id="user_email2" placeholder="Email" maxlength="50" />
<div class="errormsg" id="errormsg6"></div>
<input type="password" class="homepage" name="user_password2" id="user_password2" placeholder="Password" maxlength="20" />
<div class="errormsg" id="errormsg7"></div>
<input type="submit" name="login" id="login" value="Submit">
<div class="errormsglast" id="errormsg8"></div>
</form>
jquery and ajax
$(document).ready(function()
{
/* ----------------- Login Validations Global Variables ----------------- */
var user_email2 = "";
var user_emailajax2 = "";
var user_password2 = "";
var user_passwordajax2 = "";
var emailformat = new RegExp(/^[+a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/i);
/* ----------------- Define Validate Email */
var validate_email_login = function()
{
var item5 = $("#user_email2").val().toLowerCase();
if (item5.length < 6 || item5.length > 50)
{
$("#errormsg6").html("Email : 6 - 50 Characters");
user_email2 = "";
}
else
{
$("#errormsg6").html("");
user_email2 = item5;
if (!emailformat.test(item5))
{
$("#errormsg6").html("Wrong Email Format");
user_email2 = "";
}
else
{
$("#errormsg6").html("");
user_email2 = item5;
$.ajax(
{
type: 'POST',
url: 'classes/validatelogin.php?f=1',
data: "user_email2=" + item5,
success: function(msg)
{
if (msg == "ok")
{
user_emailajax2 = "";
$("#errormsg6").html("Email Does Not Exist");
}
else if (msg == "exists")
{
user_emailajax2 = item5;
$("#errormsg6").html("");
}
}
});
}
}
}
/* ----------------- Define Validate Password */
var validate_password_login = function()
{
var item5 = $("#user_email2").val().toLowerCase();
var item6 = $("#user_password2").val();
if (item6.length < 8 || item6.length > 20)
{
$("#errormsg7").html("Password : 8-20 Characters");
user_password2 = "";
}
else
{
$("#errormsg7").html("");
user_password2 = item6;
if (user_email2 != "" && user_emailajax2 != "")
{
$.ajax(
{
method: "POST",
url: "classes/validatelogin.php?f=2",
data: "user_email2=" + item5 + "&user_password2=" + item6,
success: function(msg)
{
if (msg == "WrongPw")
{
user_passwordajax2 = "";
$("#errormsg7").html("Wrong Password - See Forgot Password");
}
else if (msg == "CorrectPw")
{
user_passwordajax2 = item6;
$("#errormsg7").html("");
/* window.location.href="manage-properties"; */
}
}
});
}
}
}
/* ----------------- Run Functions */
$("#user_email2").on('focusout', validate_email_login);
$("#user_password2").on('focusout', validate_password_login);
/* ----------------- Stop on Submit */
$( "#login" ).mousedown(function()
{
validate_email_login();
validate_password_login();
if (user_email2 == "" || user_emailajax2 == "" || user_password2 == "" || user_passwordajax2 == "")
{
$("#errormsg8").html("Please Fill All Fields (Correctly)");
console.log("submit false");
return false;
}
else
{
$("#errormsg8").html("");
console.log("submit true");
return true;
}
});
});
Solution Tried - problem is that when user puts the wrong event that is fine, but if user then puts the correct values, the submit returns false on first time, then second time it returns true... it should return true in first go
<input type="button" name="login" id="login" value="Submit">
$( "#login" ).mousedown(function()
{
validate_email_login();
validate_password_login();
if (user_email2 == "" || user_emailajax2 == "" || user_password2 == "" || user_passwordajax2 == "")
{
$("#errormsg8").html("Please Fill All Fields (Correctly)");
console.log("submit false");
return false;
}
else
{
$("#errormsg8").html("");
console.log("submit true");
$('[name=loginform]').submit();
}
});
});
Instead of having a type="submit" button just have a normal button e.g<input type="button" name="login" id="login" value="Submit">. Then when you finished checking the values and happy that it should send then just call:
$('[name=loginform]').submit();
Because what is happening currently is that the form submits when you click on the button, because you are not stopping that event from happening.
If you want to prevent the form from submitting I would suggest either not using that button and initiating the submit yourself like I mentioned above, or alternatively you can use the onsubmit="someFunction()" on the form element way and just return false if it should not submit and return true if it should.
I would say your code suffers from a few issues and some bad practices.
I see you are trying to learn JS so forgive me for not directly solving your issue but to give you some pointers and point you to some best practices.
Logic -
It seems like you are doing a login form. I would say most of this checks should not happen in the client but on the server.
When user signups it might be wise to check user name length on the client as well and prompt the user that he can't use the user name he wants to register with, but during login all the client care is can I login or not.
Security -
You seem to have two serious security issues with your code
You allow to test if an e-mail/user exist or not using 'classes/validatelogin.php?f=1'. in general you should always test the user and password together if they exist and match the user should be able to login, if not the login should fail. you shouldn't notify the user why it fails (if the user name does not exist or if it exist but the password is wrong).
You don't seem to hash passwords in the database. I assume it by limiting the password max length. let the user choose as long password as he wants and hash it using a secure hashing algorithm (I'd suggest bcrypt but google around and find a suitable one). I know you are only learning but this is highly important I think hashing is the first thing you need to learn when handling user logins
Working with the DOM.
You should cache your DOM elements
so instead of calling $('#id') all the time in the main function scope set
var emailInput = $("#user_email2");
function submitForm() {
var email = emailInput.val().toLowerCase();
...
}
You should also probably set the text value of the element and not the html doesn't matter much now but since you are setting text value its good practice and will help you avoid unexpected injections and errors.
Since your using ajax you should not let the form to submit itself even when validation is successful.
Common logic should be packed into functions and reused.
There are many places where your original code can be split into shorter and reusable functions
handle async code better
jQuery supports the Promise API when using ajax requests, I would rather use it. Your original code had a few async calls if you needed to sync between them it would have been painful using plain callbacks (and it is probably what caused you issues in the first place)
Here is a simplified solution using my suggestions -
$(document).ready(function() {
"use strict";
var emailInput = $("#user_email2"),
emailError = $("#errormsg6"),
passwordInput = $("#user_password2"),
passwordError = $("#errormsg7");
function required (value) {
if (value) {
return true;
} else {
return false;
}
//this is just to make the code clear you could use
//`return value ? true : false` or `return !!value`
}
$('form:eq(0)').on('submit', function (e) {
var valid = true,
email = emailInput.val(),
password = passwordInput.val();
e.preventDefault();
if ( !required(email) ) {
emailError.text('Email is required');
valid = false;
}
if ( !required(password) ) {
passwordError.text('Password is required');
valid = false;
}
if ( valid ) {
$.ajax({
method: "POST",
url: "login.php",
data: {
email: email,
password: password
}
}).done(function (data, textStatus, jqXHR) {
//redirect user to main page
}).fail(function (jqXHR, textStatus, errorThrown) {
//show the user the error
})
}
});
});

JavaScript works only on first page

I have 3 forms (for login, registration and password recovery), and the following code:
document.addEventListener('DOMContentLoaded', function() {
var
login = {
user: 'afy-usr-log',
pass: 'afy-pas-log'
},
register = {
user: 'afy-usr-reg',
pass: 'afy-pas-reg',
mail: 'afy-eml-reg'
},
forget = {
user: 'afy-usr-psf',
captcha: 'afy-cpt-psf'
},
names = {
login: 'afy-usrlog',
register: 'afy-usrreg',
forget: 'afy-usrpsf'
};
document.querySelector('body').onkeyup = function() {
/* login */
if(document.getElementById(login['user']).value != '' && document.getElementById(login['pass']).value != '') {
document.getElementsByName(names['login'])[0].removeAttribute('disabled');
}
else {
document.getElementsByName(names['login'])[0].setAttribute('disabled', '');
}
/* register */
if(document.getElementById(register['user']).value != '' && document.getElementById(register['pass']).value != '' && document.getElementById(register['mail']).value != '') {
document.getElementsByName(names['register'])[0].removeAttribute('disabled');
}
else {
document.getElementsByName(names['register'])[0].setAttribute('disabled', '');
}
/* forget password */
if(document.getElementById(forget['user']).value != '' && document.getElementById(forget['captcha']).value != '') {
document.getElementsByName(names['forget'])[0].removeAttribute('disabled');
}
else {
document.getElementsByName(names['forget'])[0].setAttribute('disabled', '');
}
}
});
This code works perfectly on my main page, index.php, which contains only register form and login form, but if I add ?v=1 (which contains only password recovery form) to the address line, the script won't work anymore. (actually, it can work, if I replace the last if/else with the first one, but then the others won't work - the 1st and the 2nd if/else).
How can I solve this?
Try to change your code like this:
document.querySelector('body').onkeyup = function() {
/* login */
if(
(null !== document.getElementById(login['user']) &&
'' !== document.getElementById(login['user']).value) &&
(null !== document.getElementById(login['pass']) &&
'' !== document.getElementById(login['pass']).value) {
document.getElementsByName(names['login'])[0].removeAttribute('disabled');
}
else ...
which contains only password recovery form
If it only contains that form, then the code is going to hit the first getElementById statement, get null back from it, and then try to read the value of null.
That will throw an exception, which should have shown in in the Console of your browser's Developer Tools. (NB: It is very nearly vital that you look in the Console and quote error messages when asking questions about you code, along similar lines you should provide a [MCVE] which would include enough HTML to reproduce the problem).
Since you are getting an exception, the JS will abort.
You need to get the return value from getElementById, and then check that it is a true value (with an if) before trying to use it.
First check you are reach to code simple alert.
document.addEventListener('DOMContentLoaded', function() {
var
login = {
user: 'afy-usr-log',
pass: 'afy-pas-log'
},
register = {
user: 'afy-usr-reg',
pass: 'afy-pas-reg',
mail: 'afy-eml-reg'
},
forget = {
user: 'afy-usr-psf',
captcha: 'afy-cpt-psf'
},
names = {
login: 'afy-usrlog',
register: 'afy-usrreg',
forget: 'afy-usrpsf'
};
document.querySelector('body').onkeyup = function() {
//alert("You are in body");
console.log(document.getElementsByName(names));
}
});

How to fashion callback for results of JQuery/AJAX 'get' routine

I've read and re-read every first-page Google result on JQuery/AJAX callbacks using every permutation of terms I can think of, and no re-write I've tried for the code below is successful.
I simply need to construct a callback for this function—which is part of a larger self-calling JQuery function—so that the 'message' variable holds the results of the integrity_check.php routine before proceding to the evaluation routine of 'message' at the end.
(Yes, this is yet another attempt to make JQuery synchronous, and I understand that callbacks are the answer, but I can't find it.) May success and happiness befall you if you can help me with this:
// If the integrity check passed, message will be empty.
// If the integrity check fails, message will hold text for an alert box.
var message;
$.get('integrity_check.php', { add_new_variable: $('#new_variable').val() }, function(data) {
if (data != 0) {
message = data;
}
});
[...some other code follows that may or may not set 'message' variable to a text message for alert box, so the following code must stand independently:]
if (message != '') {
alert(message);
} else {
[...proceed with using new_variable in HTML...]
}
UPDATE
The suggestion by Guest271314 pointed in the right direction, although I had to make modifications to make it work; see CAPS commentary in code solution that follows:
var request = $.get('integrity_check.php', { add_new_variable: $('#new_variable').val() }, function(data) {
if (data != 0) {
message = data;
}
return message;
});
// HERE I HAD TO SAVE THIS VALUE TO A NEW VARIABLE;
// $('#new_variable').val(); WAS NOT ACCESSIBLE OTHERWISE IN THE ROUTINE THAT FOLLOWED:
var nv = $('#new_variable').val();
// HERE IT WAS IRRELEVANT WHAT ARGUMENT WENT INTO function(),
// EXCEPT IT COULD *NOT* BE message; YOU HAD SUGGESTED msg, WHICH WAS IMMATERIAL, IT TURNED OUT
request.then(function() {
// HERE I *HAD* TO USE message, NOT THE GENERIC msg THAT YOU HAD PASSED INTO THE FUNCTION:
if (message != '') {
alert(message);
} else {
// THE ORIGINAL FORM HERE WOULDN'T WORK, AS $('#new_variable').val() WAS INACCESSIBLE IN THE FUNCTION:
//var newKeyword = '<label><input name="new_variable[]" type="checkbox" tabindex="-1" value="' + $('#new_variable').val() + '" checked /> ' + $('#new_variable').val() + '</label>';
// THIS, HOWEVER, WORKED...USING nv IN PLACE OF $('#new_variable').val();
var newVariable = '<label><input name="new_variable[]" type="checkbox" tabindex="-1" value="' + nv + '" checked /> ' + nv + '</label>';
$('#checkboxes').append(newVariable);
}
});
I'm grateful to guest271314 for what s/he posted, although I'm unclear on why I had to make the changes that I did in order for the code to work. Elucidation, anyone?
Try utilizing deferred.then()
// If the integrity check passed, message will be empty.
// If the integrity check fails, message will hold text for an alert box.
var message;
var request = $.get('integrity_check.php'
, { add_new_variable: $('#new_variable').val() }
, function(data) {
if (data != 0) {
message = data;
}
return message
});
/*
[...some other code follows that may or may not set 'message' variable to a text message for alert box, so the following code must stand independently:]
*/
request.then(function(msg) {
// `msg`: `message`
if (msg != '') {
alert(msg);
} else {
// [...proceed with using new_variable in HTML...]
}
// return msg
}, function err(jqxhr, textStaus, errorThrown) {
console.log(errorThrown)
});

Categories