Avoid execution goes on in a .each loop - javascript

I've got a code like this one to see whether some radio buttons have been checked or not. I'm using .each function of jquery to show an alert when I find a group of radio buttons with the same name value and none of them have been checked. When I find one I want to fire an alert and return false, but after the alert is shown the execution of the .each stops but the lines after .each function are executed (I mean true value is executed).
$(":radio").each(function(){
var name = $(this).attr('name');
var numAnswered = $(":radio").filter('[name='+name+']').filter(":checked").length;
var notAnswered = numAnswered == 0;
if(notAnswered){
alert("Must answer all questions");
return false;
}
});
console.log('still goes here even when alert is fired');
return true;
How can I avoid this situation?
Thanks.

var myreturnvalue = true;
$(":radio").each(function(){
var name = $(this).attr('name');
var numAnswered = $(":radio").filter('[name='+name+']').filter(":checked").length;
var notAnswered = numAnswered == 0;
if(notAnswered){
alert("Must answer all questions");
myreturnvalue = false;
return false;
}
});
console.log('still goes here even when alert is fired');
return myreturnvalue;

You can use that same notAnswered variable (or another, whatever floats your boat) at a higher scope, like this:
var notAnswered;
$(":radio").each(function(){
notAnswered = $(":radio[name="+this.name+"]:checked").length == 0;
if(notAnswered){
alert("Must answer all questions");
return false;
}
});
if(notAnswered) return false;
console.log("will only fire if there's an answer");
return true;
The other changes above are just slimming down the code, you can get away with far fewer selector engine invocations :)

Related

Difference between JQuery $.each loop and JS for loop [duplicate]

I want to return false and return from function if I find first blank textbox
function validate(){
$('input[type=text]').each(function(){
if($(this).val() == "")
return false;
});
}
and above code is not working for me :(
can anybody help?
You are jumping out, but from the inner loop, I would instead use a selector for your specific "no value" check, like this:
function validate(){
if($('input[type=text][value=""]').length) return false;
}
Or, set the result as you go inside the loop, and return that result from the outer loop:
function validate() {
var valid = true;
$('input[type=text]').each(function(){
if($(this).val() == "") //or a more complex check here
return valid = false;
});
return valid;
}
You can do it like this:
function validate(){
var rv = true;
$('input[type=text]').each(function(){
if($(this).val() == "") {
rv = false; // Set flag
return false; // Stop iterating
}
});
return rv;
}
That assumes you want to return true if you don't find it.
You may find that this is one of those sitautions where you don't want to use each at all:
function validate(){
var inputs = $('input[type=text]');
var index;
while (index = inputs.length - 1; index >= 0; --index) {
if (inputs[index].value == "") { // Or $(inputs[index]).val() == "" if you prefer
return false;
}
}
// (Presumably return something here, though you weren't in your example)
}
I want to add something to existing answers to clear the behavior of $(selector).each and why it doesn't respect return false in OP's code.
return keyword inside $(selector).each is used to break or continue the loop. If you use return false, it is equivalent to a break statement inside a for/while loop. Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration. Source
Because you're returning false, the loop breaks and the function ends up returning undefined in your case.
Your option is to use a var outside $.each or avoid using it altogether as #TJCrowder wrote.

If checbox/disable element not working properly

I'm attempting to make a script so that if you check/uncheck a checkbox input, that it will enable/disable a target input text box. My code if statement doesn't seem to function correctly sometimes firing both ifs at once, other times not firing at all. I've done debugging and tried numerous variations but it still won't work. Here is what I have, any help is greatly appreciated!
function disable(elem) {
var obj = document.getElementById(elem);
status = obj.disabled;
console.log(status);
if (status = true) {
console.log("test");
obj.disabled = false;
obj.style.backgroundColor = "white";
}
if (status = false) {
console.log("test2");
obj.disabled = true;
obj.style.backgroundColor = "bfbfbf";
}
}
This code is not exhibiting proper behavior for several reasons.
The first reason is that your if statements are inline, not in an if-else form. A better organization is as follows:
function disable(elem) {
var obj = document.getElementById(elem);
status = obj.disabled;
console.log(status);
if (status == true) {
console.log("test");
obj.disabled = false;
obj.style.backgroundColor = "white";
} else {
console.log("test2");
obj.disabled = true;
obj.style.backgroundColor = "#bfbfbf";
}
}
This means that even if the variable you are checking changes while the code in the block is executing, it will not execute the code in the opposing block regardless of its new value. As you have it, if the value were to change while the code in the first if statement was running, then it is possible for both control blocks to run.
The second reason it is not behaving right is due to the incorrect syntax within your if statement. You are currently using the = operator which means set the variable to what you are wanting to check against. You must use either the == or === equality checks (the latter is type strict) if you want to write them this way. An even better way is to omit that operator entirely by just checking if the value is truthy, like so:
function disable(elem) {
var obj = document.getElementById(elem);
status = obj.disabled;
console.log(status);
if (status) {
console.log("test");
obj.disabled = false;
obj.style.backgroundColor = "white";
} else {
console.log("test2");
obj.disabled = true;
obj.style.backgroundColor = "#bfbfbf";
}
}
This should give you your expected control behavior :) As was mentioned, make sure you are formatting your values appropriately (e.g. "#bfbfbf" not "bfbfbf")

Check whether function has run fully before, based on variable

I have a function which "types" out a header title as though it is being typed on the screen.
The typer only starts typing once a particular section of my site is "active" or is seen on the screen.
At present, it takes the outputID aka the area where this text will be typed into. There are two instances of this function being run, each with different outputIDs - I only want the function to run once per outputID.
This is how the function is initially called.
<h2 id="typer-get-in-touch" class="typer" data-text="Get in Toche^^^^^ Touch"></h2>
if(anchorLink == 'contact'){
var outputID = $("#typer-get-in-touch");
textTyping(outputID);
}else if(anchorLink == 'expertise'){
var outputID = $("#typer-expertise");
textTyping(outputID);
}
This is the textTyping function
function textTyping(outputID){
$(outputID).show();
var textString = $(outputID).data("text");
var textArray = textString.split("");
var texttypeing = setInterval(
function() {
typeOutText(outputID,textArray);
}, 170);
function typeOutText(outputID,textArray) {
if (textArray[0] == "^"){
outputID.text(function(index, text){
return text.replace(/(\s+)?.$/, '');
});
textArray.shift();
}else {
if (textArray.length > 0) {
outputID.append(textArray.shift());
} else {
clearTimeout(texttypeing);
}
}
}
}
My issue at present is that the function runs multiple types, and continues to type each time the original anchorLink trigger is achieved. The result is that is writes the title many times e.g:
Get In TouchGet In TouchGet In Touch
Each time the section is navigated to, the typing starts again.
How can I run this function only ONCE per outputID? So once the outputID has been used, the function can no longer run for that data?
JSFiddle of non-working example: https://jsfiddle.net/qLez8zeq/
JSFiddle of mplungjan's solution: https://jsfiddle.net/qLez8zeq/1/
Change
function textTyping(outputID){
$(outputID).show();
var textString = $(outputID).data("text");
to
function textTyping(outputID){
var textString = $(outputID).data("text");
if (textString=="") return;
$(outputID).data("text","");
$(outputID).show();
FIDDLE
What you need to do is to bind the event handler for each ID and then unbind it after it's been triggered the first time. Since you're already using jQuery, you can use the "one" method to do exactly this for each outputID:
$( "#typer-get-in-touch" ).one( "click", function() {
textTyping(outputID);
});
I suppose you could store your processed outputIds into an array and then check if the given outputId is present in the array before starting?
Define your array, check for the existence, if not found, do code example:
var processedIds = [];
function textTyping(outputID) {
var foundItem = false;
for (var i = 0; i < processedIds.length; i++)
{
if (processedIds[i] == outputID) {
foundItem = true;
break;
}
}
if (!foundItem) {
//the rest of your code goes here
}
}
You can add some check at the beginning of your function:
var called = {};
function textTyping(outputID) {
if (called[outputID]) {
return;
}
called[outputID] = true;
// your code
}

Why wont my function return true?

I cant seem to get this function to return true even after ticking the two check boxes I have on the page. I've been working on this for hours now and running out of ideas. Any help would be much appreciated.
if(myfunction() == true){
alert('YAY!');
}
function myfunction(){
if($("input[type=checkbox]").length > 0){
$('.checkbox').each(function(){
if($(this).prop('checked')){
return true;
}
else{
$(this).find(".CheckboxCheck").show();
return false;
}
});
}
else{
return true;
}
}
You are returning true from within the function that you passed to each, not from myfunction. Except in the case that there are no check boxes on your page, and thus the else block executes in myfunction, myfunction is returning undefined.
You can do something like this however:
if(myfunction() == true){
alert('YAY!');
}
function myfunction(){
var returnValue = true;
if($("input[type=checkbox]").length > 0) {
$('.checkbox').each(function(){
if($(this).prop('checked')){
returnValue = true;
return false; // Stops the each loop.
}
else {
$(this).find(".CheckboxCheck").show();
returnValue = false;
return false; // Stops the each loop.
}
});
}
return returnValue;
}
Now, I'm not exactly sure of what you're trying to do, and you will almost certainly need to tweak the code above. I'm just providing it as a way to illustrate how to get a value out of the function passed to each. If you're trying to determine if all of the checkboxes are checked, for example, then you'll want your each function to look something like this:
var returnValue = true;
...
$('.checkbox').each(function() {
if (!$(this).prop('checked')) {
returnValue = false;
return false;
}
});
EDIT: After looking at the second code snippet again, I realized that the each loop is unnecessary. If you want to determine if all check boxes are checked, all you need is this:
if ($('.checkbox:not(:checked)').length == 0) {
// All .checkbox elements are checked.
}
Now, keep in mind that the :not() and :checked selectors can't utilize the native JS functions, so they are slower, but probably not enough to matter. I prefer the conciseness.
Returning from inside the each callback function will not return from the outer function. The function will return undefined as you haven't specified any return value for it, and that is not equal to true.
You can use a variable for the result, that you set from within the loop:
function myfunction(){
var result = true;
$('.checkbox').each(function(){
if(!$(this).prop('checked')){
result = false;
$(this).find(".CheckboxCheck").show();
return false; // exit the loop
}
});
return result;
}

Why does the following javascript function always return true?

I have the following function, it will always return True. Any ideas why and how to avoid it? Thanks folks.
function validateStatuses(xyx){
var umm = ugh[xyx];
var selects = $('#cont_'+ugh.xyz+' .status_select');
var codes = $('#cont_'+ugh.xyz+' .status_code');
for (var i = 0; i < selects.length; i++) {
var value = selects[i].options[selects[i].selectedIndex].value;
if (value == 'new'){
for (var j = 0; j < codes.length; j++) {
var blagh = codes[j].options[codes[j].selectedIndex].value;
if(blagh == 13){
$('#info_dialog').html('');
$('#info_dialog').append("<p>You are trying to process a bill ("+bill.name+") with a STATUS of NEW and a STATUS CODE of NONE. Please correct this issue before you proceed!</p><hr />");
$('#info_dialog').dialog({
buttons:{
Cancel: function(){
$(this).dialog('close');
}
}
});
billCounterAdd();
return false;
}//end if
}//end for
}else{
return true; //this is the problem;
}//end if
}//end for
}//end Function
I dare say you have at least one select whose value isn't 'new'. Because you've done a return true; in the else clause, the first select with a value that isn't 'new' will cause the function to return true.
It looks like it does have a false return route (if there's a 'new' select at the beginning and there's a code select with the value 13), but perhaps that test case didn't come up in your testing.
In terms of figuring out what's wrong with things like this, there's nothing quite like walking through the code and watching it run line-by-line in a decent debugger. All major browsers have them built in now (finally), so you can see exactly what's happening and inspect variables, etc.

Categories

Resources