JQuery $().each exiting too early - javascript

I'm using the function below to validate several input fields on a web form. The function iterates through the fields using jQuery .each() iteration. The ValidateInput function validates each individal input field, returning a true or false.
function ValidateForm() {
var result = true;
$('[data-regex]').each(function() {
result = result && ValidateInput(this);
// return true;
});
if ( result == false ) {
$(".alert").show();
}
return result;
}
The problem I'm having is that the .each() is terminating early, as soon as any individual input field fails validation. I know that if function() returns false, the .each() will terminate, but I don't see how I'm doing that. I've even tried adding an explicit return true; as the last line of function(), but this made no difference.
For completeness, here's ValidateInput:
function ValidateInput(thisInput) {
var fieldName = $(thisInput).attr('name');
var fieldValue = $(thisInput).val();
var regex = $(thisInput).attr('data-regex');
console.log('validating field "' + fieldName + '" value "' + fieldValue + '" with regEx "' + regex + '"';
var re = new RegExp(regex);
var result = re.test(fieldValue);
if ( result ) {
console.log('- passed');
$(thisInput.closest(".form-group")).addClass("has-success").addClass("has-feedback")
} else {
console.log('- failed');
$(thisInput.closest(".form-group")).addClass("has-error").addClass("has-feedback")
};
return result;
}
The code that calls ValidateForm is as follows:
<input type="submit" name="ct108" value="Save User" onclick="return ValidateForm();" />
What am I missing?

Your ValidateInput method stops processing after the first one that doesn't pass validation because this line:
result = result && ValidateInput(this);
The way && works is that if the item on the left side is truthy the value on the right is returned as the value, otherwise the value on the left is returned as the value.
You can guarantee that each one is processed by flipping it around:
result = ValidateInput(this) && result;

Related

How can I run recursive function in cypress or find length with async await

I am running tests using Cypress.
I have an array of Litecoin addresses. I am trying to set first in the input. Then submit the form.
If the address is duplicate then a notification is displayed and submit button will be not visible. The same I want to set for the second element and so on till end of the array.
I tried recursive function:
function runTillElementFound (totalCount, currentCount, litecoin_addresses)
{
var self = this;
if (currentCount < totalCount) {
return cy.get('body').then(($body) =>
{
if ($body.find(dash_page.save_wallet_circle_btn)) {
//if there is save button then set address and submit form
cy.log('taken address: ' + litecoin_addresses[ currentCount ]);
dashact.fill_wallet(litecoin_addresses[ currentCount ]);
cy.log('address is filled');
dashact.submit_wallet(true, 0);
self.runTillElementFound(totalCount, currentCount++);
}
});
} else {
return false; //if element not present after Max count reached.
}
I try to call it:
it('Set wallet', () =>
{
cy.log('this is array length: ' + litecoin_addresses);
runTillElementFound(20, 0, litecoin_addresses);
/* comact.submit_form(true, 1);
let ltc_address = promisify(dashact.get_wallet_value());
cy.log('this is address: ' + ltc_address);
//close popup and check that it is closed:
popact.submit_payment(); */
});
However I receive undefined:
I have also tried non recursive function:
for (var i = 0; i < litecoin_addresses.length; i++) {
cy.log('taken address: ' + litecoin_addresses[ i ])
if (litecoin_addresses[ i ] == wallet_before_edit || litecoin_addresses[ i ].length == 0 || litecoin_addresses[ i ].startsWith('ltc')) {
continue;
}
else {
cy.log('this is curent i: ' + i);
dashact.fill_wallet(litecoin_addresses[ i ]);
dashact.submit_wallet(true, null);
cy.get('body').then(($body) =>
{
// synchronously query from body
// to find which element was created
if ($body.find(com_page.not_message).length) {
// error was found, do something else here
cy.log('error was found');
}
else {
cy.log('error not found');
// input was not found, do something else here
i = litecoin_addresses.length;
cy.log('current i value: ' + i);
}
})
}
However it for sure, does not work, as i inside promise has one valued but in the loop it still remains the same.
If you use a specific array in your test code, you can easily get the length of the array by using the .lenght and access its elements by using the for loop.

listbox does not pass string to google script

When I select a user from listbox, the onChange() event triggers a function. It should pass a string to the function. Then the code finds the user's password and returns it for comparison. The following is the code which works fine if I hard code the user value, but not when I select it from the listbox.
function addClients(clients){
$('#customer').empty();
$('#customer').append('<option> ---- Choose a user ----</option>');
for (var i in clients) {
$('#customer').append('<option>'+clients[i]+'</option>');
$('#customer').trigger("chosen:updated");
}
}
getval function:
function getval(sel){
var usrpass = google.script.run.getuserpass(sel.value);
alert(usrpass);
}
the function in code.gs is as follows
function getuserpass(userval){
var usrpass = "";
var doc = SpreadsheetApp.openById("spreadsheet id");
var sheet = doc.getActiveSheet();
var data = sheet.getRange(3, 3, sheet.getLastRow(),5).getValues();;
for(n=0;n<data.length;++n){
// iterate row by row and examine data in column A
if(data[n][0].toString().match(userval)==userval){ usrpass = data[n][4]};
}
return usrpass;
}
Why does the return value come back as undefined rather than the password.
If I hardcode username in the function and run the function, then the return value is the value in the fifth column.
Try structuring the code like this:
<script>
function onSuccess(returnVal) {
alert('Success! ' + returnVal);
};
function getval(sel){
var selectValue = sel.value;
console.log('selectValue: ' + selectValue);
google.script.run
.withSuccessHandler(onSuccess)
.getuserpass(sel.value);
};
</script>
You can iterate through the object to see what is really in it, as a debugging test.
for (var propertyVal in sel) {
console.log('this property: ' + propertyVal);
console.log('this value: ' + sel[propertyVal]);
};
And see what is really in the object.

Validate Spreadsheet in a HTML Service

I have an html form I created with HTML Service in Google Sheets. The form has three fields in it. I want to check if the data they entered in one of the fields is contained in a column of sheet2. If it is not, I just want to display an alert box saying "invalid input". Whats the best way to do this? This is my submit form. The line of code that compares the value to "test", is where I want to check against a value in the spreadsheet.
function formSubmit() {
if (document.getElementById("sku").value === "test") {
alert(document.getElementById("sku").value);
} else {
google.script.run.appendRowstoSheet(document.forms[0]);
document.getElementById("sku").value = ' ';
document.getElementById("sku").focus();
}
}
gs Code:
//insertValuestoSheet
function appendRowstoSheet(form){
var sku = form.sku,
loc_array = [{}];
location = form.location,
reference = form.reference
loc_array = location.split("-");
sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
//validateMySheet();
//don't insert blank sku's
//Also want to have it so it doesn't insert values where if the sku
//doesn't match a sku in sheet2, column A. Alert the user if this condition
if (sku != " ") {
sheet.appendRow(["'"+reference," "," "," ","'"+sku, "1", " ", " ", " ", "'"+loc_array[0],"'"+loc_array[1],"'" + loc_array[2],"'"+loc_array[3]]);
}
}
I modified my code with a better function name and added the function. Currently in appendRowstoSheet, it inserts into the spreadsheet. How do I return a failure here if my condition isn't met. Am I understanding that correctly?
You need to return something:
if (sku != " ") {
sheet.appendRow(["'"+reference," "," "," ","'"+sku, "1", " ", " ", " ", "'"+loc_array[0],"'"+loc_array[1],"'" + loc_array[2],"'"+loc_array[3]]);
return true;
} else {
return false;
};
Note the use of return true; and return false;. Either true or false will be returned to your HTML code and passed to the success handler.
You need to run a withSuccessHandler() and do the final processing in that separate "success" function. First get the data out of the spreadsheet. Then if that is successful, a different function will run that compares the values.
<script>
function onSuccess(argReturnValue) {
Console.log('argReturnValue: ' + argReturnValue);
if (argReturnValue === true) {
//Code here
} else {
};
//Note that the argument: argValuesFromSpreadsheet is the return value from
//the gs script function, "getValuesFromForm"
var valueFromForm = document.getElementById("sku").value;
//You'll need to modify this line to get a specific value
var valueFromSpreadsheet = argValuesFromSpreadsheet[0];
Logger.log('valueFromSpreadsheet: ' + valueFromSpreadsheet);
if (valueFromForm === valueFromSpreadsheet) {
alert('alert text here: ' + document.getElementById("sku").value);
} else {
document.getElementById("sku").value = ' ';
document.getElementById("sku").focus();
}
}
function formSubmit() {
google.script.run
.withSuccessHandler(onSuccess)
.getValuesFromForm(document.forms[0]);
};
</script>
Note: You will need to make some modifications to the code, depending on what data, and the format of the data being returned from the spreadsheet:
var valueFromSpreadsheet = argValuesFromSpreadsheet[0];
That line needs to be modified.

Display All ().html in Javascript

Sorry for the lack of description in title, it's difficult to explain.
So I have a simple signup page and I made a bunch of functions in my code that check things such as the username length, make sure the passwords match, etc..
The problem is, if there is more than one error in the users input, it only displays one error at the bottom.
HEre is the JSfiddle: http://jsfiddle.net/LCBradley3k/xqcJS/19/
Javascript:
$('#join').on('click', function () {
var correct = true;
$('input[type="text"], input[type="password"]').each(function (indx) {
var $currentField = $(this);
if ($currentField.val() === '') {
$currentField.addClass('empty');
correct = false;
$currentField.one('keydown', function () {
$currentField.removeClass('empty');
});
} else {
$currentField.removeClass('empty');
}
});
function userLength() {
var x = $('input[name="user"]').val();
if (x.length < 6) {
$('#answer').html('Less than six characters.');
$('input[name="user"]').addClass('empty');
return false;
} else {
return true;
}
}
function passwordCheck() {
var x = $('input[name="password"]').val();
var y = $('input[name="passwordcheck"]').val();
if (x === y) {
return true;
} else {
$('#answer').html('Two different passwords');
$('input[name="password"], input[name="passwordcheck"]').addClass('empty');
return false;
}
}
function validateForm() {
var x = $('input[name="email"]').val();
if (x.indexOf('#') !== -1 && x.lastIndexOf(".") !== -1) {
return true;
} else {
$('#answer').html('Not a valid email');
$('input[name="email"]').addClass('empty');
return false;
}
}
if (correct) {
if (userLength()) {
if (passwordCheck()) {
if (validateForm()) {
$('#answer').html('Thank You!');
setTimeout(function () {
$('.inputs').hide("slide", {
direction: "up"
}, 1000);
}, 2000);
}
}
}
} else {
$('#answer').html('Please fill highlighted fields.');
}
});
You can see that all of them edit the #('#answer') div with .html(). But only one is displayed when there is more than one error. Once that error is fixed and the button is pressed, it will then display the next error. I want them all to be displayed in a list.
I created a fiddle that may be of some help. The idea is to create an array with the errors in it like so:
var errors = [];
errors.push("Error 1");
errors.push("Error 2");
As you step through the validation, every time an error is encountered you simply push the error string onto the array. When you get to the end of the validation you need to compile these errors into html like that can be appended to your $('#answer') element. In this case the items are compiled into an unordered list. You can change this to fit your needs.
var content = "<ul>";
for(var a = 0, len = errors.length; a < len; a++) {
content += "<li>" + errors[a] + "</li>";
}
content += "</ul>";
$('#answer').html(content);
The html is built dynamically and stored in the variable content. content is then appended to your html element that displays the errors (in your case answer).
You have 2 issues with doing what you want.
First, you are only continuing your checks if the first one passes, due to your nested if statements.
Second, you are replacing the #answer html with the message, which means even if you do each check, you will only see the results of the last one.
A simple fix would be to un-nest your if statements, and keep a variable that tracks the overall pass state. Secondly, instead of using .html(), use .append(), but make sure to clear out #answer before starting your checks.
correct &= checkFilled();
correct &= userLength();
correct &= passwordCheck();
correct &= validateForm();
if (correct) {
// ...
}
Fiddle: http://jsfiddle.net/jtbowden/9cFKW/
Note: I made your form filled check it's own function to work better with this method.
You can do some more fancy things, like pushing error messages on an array, and then checking the array for errors at the end and appending all of the messages, but this should get you started.

$.post issue in Jquery specific scenario

Let me share my jQuery part first
$(".btnUpdateInput").click(function() {
//alert("Update");
var BldDocumentId = $("#BldDocId").val();
var BldinstructionId = $("#BldIPInstnId").val();
var InputFieldId = $("#InputFieldId").val();
var InputFieldValue = jQuery.trim($(this).parent().prev().text()); //$("#InputFieldValue").val();
var InputFieldUserValue = jQuery.trim($(this).prev().val()); // $(".user_input_value").val();
alert(BldDocumentId + "," + BldinstructionId + "," + InputFieldId + "," + InputFieldValue + "," + InputFieldUserValue);
var postResult;
alert($(this).get());
$.post("/Build/UpdateInputField",
{ bldDocId: BldDocumentId, bldInstnId: BldinstructionId, inputFieldId: InputFieldId, inputFieldValue: InputFieldValue, inputFieldUserValue: InputFieldUserValue },
function(result) {
postResult = result;
//Either this should function**
alert($(this).get()); // returned Object[Object] but expected the clicked button
alert($(this).parent().get());// returned null
alert($(this).parent().next().get());//returned null
alert($(this).parent().next().children().first().get());// returned null
// $(this).parent().next().show();
// $(this).parent().next().children().first().text(InputFieldUserValue);
// $(this).parent().hide();
});
alert(postResult);
//Or this should function**
if (postResult == true) {
$(this).parent().next().show();
$(this).parent().next().children().first().text(InputFieldUserValue);
$(this).parent().hide();
}
});
Now let me explain my issue. I need to show and hide few divs with respect to the button "btnUpdateInput" I clicked. I tried it in two ways: 1. I gave the following lines in the in the success part of $.post
$.post("/Build/UpdateInputField",
{ bldDocId: BldDocumentId, bldInstnId: BldinstructionId, inputFieldId: InputFieldId, inputFieldValue: InputFieldValue, inputFieldUserValue: InputFieldUserValue },
function(result) {
postResult = result;
//Either this should function**
alert($(this).get()); // returned Object[Object] but expected the clicked button
alert($(this).parent().get());// returned null
alert($(this).parent().next().get());//returned null
alert($(this).parent().next().children().first().get());// returned null
// $(this).parent().next().show();
// $(this).parent().next().children().first().text(InputFieldUserValue);
// $(this).parent().hide();
});
2. or get the value of postResult out and compare and do the same there. The code is bellow:
if (postResult == true) {
$(this).parent().next().show();
$(this).parent().next().children().first().text(InputFieldUserValue);
$(this).parent().hide();
}
Neither works for me. In 1 am not getting $(this) as the button 'btnUpdateInput' that i click and 2. the value of postResult is undefined since there is no delay so that postResult is assigned to result of post action.
Please help me out with either of the scenario.
This is the element in your current IN. So in the SUCCES its in the return.
So in method one you could do:
$(".btnUpdateInput").click(function(e) {
var self = e;
//code
alert($(self).get()); // returned Object[Object] but expected the clicked button
alert($(self).parent().get());// returned null
alert($(self).parent().next().get());//returned null
alert($(self).parent().next().children().first().get());// returned null
}
Seems self is also used as default....
Try this instead:
$(".btnUpdateInput").click(function(e) {
var myButton = $(this);
//code
alert($(myButton).get()); // returned Object[Object] but expected the clicked button
alert($(myButton).parent().get());// returned null
alert($(myButton).parent().next().get());//returned null
alert($(myButton).parent().next().children().first().get());// returned null
}

Categories