This is my code
function nameIsDuplicate(name){
objects = $("#content").find('p.itemOldName');
$(objects).each(function(i, object){
console.log("*"+($(object).text()).toLowerCase() + "*" + name.toLowerCase()+"*");
if(($(object).text()).toLowerCase() == name.toLowerCase())
return true;
});
return false;
}
I am building an online file manager system.
the name argument is a name provided by the user via a textbox, and the $(object).text() is the name of files and folders in the current directory. These names come via exec("ls") command.
I need to check if the name provided by the user already exists. So I compare the name with every files/folders name. The problem is it doesn't find duplicates. The result of the above code is given in the following image
The return true returns out of the each callback. That has no effect on each (it only cares about return false) and doesn't do anything to set the return value of nameIsDuplicate.
You want to return false there (no need to keep looking) and set a flag so your nameIsDuplicate can return it:
function nameIsDuplicate(name){
var duplicate = false;
objects = $("#content").find('p.itemOldName');
$(objects).each(function(i, object){
console.log("*"+($(object).text()).toLowerCase() + "*" + name.toLowerCase()+"*");
if(($(object).text()).toLowerCase() == name.toLowerCase()) {
duplicate = true;
return false; // Stop looping
}
});
return duplicate;
}
However, that function can be a lot simpler using Array.prototype.some:
function nameIsDuplicate(name){
var objects = $("#content").find('p.itemOldName');
name = name.toLowerCase();
return objects.get().some(function(object) {
return $(object).text().toLowerCase() === name;
});
}
some calls its callback for each entry in the array. If the callback returns a falsy value, some keeps going; if the callback returns a truthy value, some stops. some's return value is true if a call to the callback returned a truthy value, false if not.
Your function doesn't return true, because you are in each loop... should be something like this:
function nameIsDuplicate(name){
var same=0;
objects = $("#content").find('p.itemOldName');
$(objects).each(function(i, object){
console.log("*"+($(object).text()).toLowerCase() + "*" + name.toLowerCase()+"*");
if(($(object).text()).toLowerCase() == name.toLowerCase()){
same=1;
return false;
}
});
if(same){
return true;
}else{
return false;
}
}
We can break the $.each() loop at a particular iteration by making the
callback function return false. Returning non-false is the same as a
continue statement in a for loop; it will skip immediately to the next
iteration.
Other solution:
function nameIsDuplicate(name){
return $("#content").find('p.itemOldName').filter(function(){return $(this).text().toLowerCase() === name.toLowerCase();}).length;
}
Related
How do I break out of a jQuery each loop?
I have tried:
return false;
in the loop but this did not work. Any ideas?
Update 9/5/2020
I put the return false; in the wrong place. When I put it inside the loop everything worked.
To break a $.each or $(selector).each loop, you have to return false in the loop callback.
Returning true skips to the next iteration, equivalent to a continue in a normal loop.
$.each(array, function(key, value) {
if(value === "foo") {
return false; // breaks
}
});
// or
$(selector).each(function() {
if (condition) {
return false;
}
});
According to the documentation return false; should do the job.
We can break the $.each() loop [..] by making the callback function
return false.
Return false in the callback:
function callback(indexInArray, valueOfElement) {
var booleanKeepGoing;
this; // == valueOfElement (casted to Object)
return booleanKeepGoing; // optional, unless false
// and want to stop looping
}
BTW, continue works like this:
Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
I came across the situation where I met a condition that broke the loop, however the code after the .each() function still executed. I then set a flag to "true" with an immediate check for the flag after the .each() function to ensure the code that followed was not executed.
$('.groupName').each(function() {
if($(this).text() == groupname){
alert('This group already exists');
breakOut = true;
return false;
}
});
if(breakOut) {
breakOut = false;
return false;
}
I created a Fiddle for the answer to this question because the accepted answer is incorrect plus this is the first StackOverflow thread returned from Google regarding this question.
To break out of a $.each you must use return false;
Here is a Fiddle proving it:
http://jsfiddle.net/9XqRy/
I know its quite an old question but I didn't see any answer, which clarify that why and when its possible to break with return.
I would like to explain it with 2 simple examples:
1. Example:
In this case, we have a simple iteration and we want to break with return true, if we can find the three.
function canFindThree() {
for(var i = 0; i < 5; i++) {
if(i === 3) {
return true;
}
}
}
if we call this function, it will simply return the true.
2. Example
In this case, we want to iterate with jquery's each function, which takes anonymous function as parameter.
function canFindThree() {
var result = false;
$.each([1, 2, 3, 4, 5], function(key, value) {
if(value === 3) {
result = true;
return false; //This will only exit the anonymous function and stop the iteration immediatelly.
}
});
return result; //This will exit the function with return true;
}
"each" uses callback function.
Callback function execute irrespective of the calling function,so it is not possible to return to calling function from callback function.
use for loop if you have to stop the loop execution based on some condition and remain in to the same function.
I use this way (for example):
$(document).on('click', '#save', function () {
var cont = true;
$('.field').each(function () {
if ($(this).val() === '') {
alert('Please fill out all fields');
cont = false;
return false;
}
});
if (cont === false) {
return false;
}
/* commands block */
});
if cont isn't false runs commands block
I am writing a calculator program with a user interface similar to a real calculator. Everything had been going fine (unusual for me xD) until I needed to have multiple values returned from one function (I read on another post that this can be done with an array). I haven't been returning the values to any specific place so I think they are just being sent out to the global scope, and this has worked so far with other functions like updateDisplay(). However, when I try to return returnValue from operationClick(), it doesn't send the changes outside of the function.
Here are some bits and pieces of my code (hopefully enough so you can find what I'm doing wrong):
returnValue = [false, undefined];
numberArray = new Array;
function operationClick(operation, concat, returnValue) {
if (operation == "equals") {
concatComplete = returnValue[1] + concat;
$('.screen_text').html(Number(concatComplete));
}
else if (operation == "add") {
returnValue = [true, concat + "+"];
console.log(returnValue); // The new value is correct here but not anywhere else :(
}
return returnValue; // Something goes wrong here!
}
function updateDisplay(array) {
concat = array.join("");
$('.screen_text').html(concat);
return concat
}
function numberClick(number, returnValue) {
if (returnValue[0] == true) {
// This should run once operationClick() else if statement runs but it doesn't
numberArray = new Array;
$('.screen_text').html("");
}
numberArray.push(number);
updateDisplay(numberArray);
return numberArray;
}
$('.button_1').click(function(){
numberClick(1, returnValue);
});
$('.button_addition').click(function(){
operationClick("add", concat);
})
$('.button_equals').click(function(){
operationClick("equals", concat, returnValue);
})
Thank you in advance for your help. It is greatly appreciated! I hope my code isn't too messy.
As mentioned in the comments, returning a value doesn't automatically update anything, you need to do something with the returned value in the caller. If you want to replace the returnValue global variable with the new value, do it with an assignment.
$('.button_addition').click(function(){
returnValue = operationClick("add", concat);
});
This doesn't happen in the operationClick() function itself because it has declared a local variable named returnValue (function parameters are automatically made local variables), and this shadows the global variable. You could also solve the problem simply by giving the function parameter a different name.
function operationClick(operation, concat, oldReturnValue) {
if (operation == "equals") {
concatComplete = oldReturnValue[1] + concat;
$('.screen_text').html(Number(concatComplete));
}
else if (operation == "add") {
returnValue = [true, concat + "+"];
console.log(returnValue); // The new value is correct here but not anywhere else :(
}
}
How do I break out of a jQuery each loop?
I have tried:
return false;
in the loop but this did not work. Any ideas?
Update 9/5/2020
I put the return false; in the wrong place. When I put it inside the loop everything worked.
To break a $.each or $(selector).each loop, you have to return false in the loop callback.
Returning true skips to the next iteration, equivalent to a continue in a normal loop.
$.each(array, function(key, value) {
if(value === "foo") {
return false; // breaks
}
});
// or
$(selector).each(function() {
if (condition) {
return false;
}
});
According to the documentation return false; should do the job.
We can break the $.each() loop [..] by making the callback function
return false.
Return false in the callback:
function callback(indexInArray, valueOfElement) {
var booleanKeepGoing;
this; // == valueOfElement (casted to Object)
return booleanKeepGoing; // optional, unless false
// and want to stop looping
}
BTW, continue works like this:
Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
I came across the situation where I met a condition that broke the loop, however the code after the .each() function still executed. I then set a flag to "true" with an immediate check for the flag after the .each() function to ensure the code that followed was not executed.
$('.groupName').each(function() {
if($(this).text() == groupname){
alert('This group already exists');
breakOut = true;
return false;
}
});
if(breakOut) {
breakOut = false;
return false;
}
I created a Fiddle for the answer to this question because the accepted answer is incorrect plus this is the first StackOverflow thread returned from Google regarding this question.
To break out of a $.each you must use return false;
Here is a Fiddle proving it:
http://jsfiddle.net/9XqRy/
I know its quite an old question but I didn't see any answer, which clarify that why and when its possible to break with return.
I would like to explain it with 2 simple examples:
1. Example:
In this case, we have a simple iteration and we want to break with return true, if we can find the three.
function canFindThree() {
for(var i = 0; i < 5; i++) {
if(i === 3) {
return true;
}
}
}
if we call this function, it will simply return the true.
2. Example
In this case, we want to iterate with jquery's each function, which takes anonymous function as parameter.
function canFindThree() {
var result = false;
$.each([1, 2, 3, 4, 5], function(key, value) {
if(value === 3) {
result = true;
return false; //This will only exit the anonymous function and stop the iteration immediatelly.
}
});
return result; //This will exit the function with return true;
}
"each" uses callback function.
Callback function execute irrespective of the calling function,so it is not possible to return to calling function from callback function.
use for loop if you have to stop the loop execution based on some condition and remain in to the same function.
I use this way (for example):
$(document).on('click', '#save', function () {
var cont = true;
$('.field').each(function () {
if ($(this).val() === '') {
alert('Please fill out all fields');
cont = false;
return false;
}
});
if (cont === false) {
return false;
}
/* commands block */
});
if cont isn't false runs commands block
Im trying to check if a value is taken, and if it is then im skipping to the next value . This is done by a simple recursion
function recur(id){
if($('#'+id).length != 0){ // checking if id exists on page
recur(id++);
}
else{
return id;
}
}
$.(document).ready(function(){
var x = recur(1);
alert(x);
});
But I get this error:
x is undefined
return proxy
You are missing a return statement for the recursive call:
function recur (id){
if($('#'+id).length != 0){
return recur(id++); // add return here
}
else{
return id;
}
Without it, only the terminating case will return a value, but it won't get passed up the stack. So the top-most recur call does actually return undefined.
I personally would not use recursion but rather do it iteratively:
function nextId(id) {
while ($('#'+id).length != 0) {
++id;
}
return id;
}
Object.prototype.e = function() {
[].forEach.call(this, function(e) {
return e;
});
};
var w = [1,2];
w.e(); // undefined
But this works if I use alert instead
// ...
[].forEach.call(this, function(e) {
alert(e);
});
// ...
w.e(); // 1, 2
I realize this is an old question, but as it's the first thing that comes up on google when you search about this topic, I'll mention that what you're probably looking for is javascript's for.. in loop, which behaves closer to the for-each in many other languages like C#, C++, etc...
for(var x in enumerable) { /*code here*/ }
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/for...in
http://jsfiddle.net/danShumway/e4AUK/1/
A couple of things to remember :
for..in will not guarantee that your data will be returned in any particular order.
Your variable will still refer to the index, not the actual value stored at that index.
Also see below comments about using this with arrays.
edit: for..in will return (at the least) added properties to the prototype of an object. If this is undesired, you can correct for this behavior by wrapping your logic in an additional check:
for(var x in object) {
if(object.hasOwnProperty(x)) {
console.log(x + ": " + object[x]);
}
}
Your example is a bit odd, but as this question is becoming the canonical "return from forEach" question, let's use something simpler to demonstrate the problem:
Here, we have a function that checks the entries in an array to see if someProp matches value and, if so, increments the count on the entry and returns the entry:
function updateAndReturnMatch(array, value) {
array.forEach(function(entry) {
if (entry.someProp == value) {
++entry.count;
return entry;
}
});
}
But calling updateAndReturnMatch gives us undefined, even if the entry was found and updated.
The reason is that the return inside the forEach callback returns from the callback, not from updateAndReturnMatch. Remember, the callback is a function; return in a function returns from that function, not the one containing it.
To return from updateAndReturnMatch, we need to remember the entry and break the loop. Since you can't break a forEach loop, we'll use some instead:
function updateAndReturnMatch(array, value) {
var foundEntry;
array.some(function(entry) {
if (entry.someProp == value) {
foundEntry = entry;
++foundEntry.count;
return true; // <== Breaks out of the `some` loop
}
});
return foundEntry;
}
The return true returns from our some callback, and the return foundEntry returns from updateAndReturnMatch.
Sometimes that's what you want, but often the pattern above can be replaced with Array#find, which is new in ES2015 but can be shimmed for older browsers:
function updateAndReturnMatch(array, value) {
var foundEntry = array.find(function(entry) {
return entry.someProp == value;
});
if (foundEntry) {
++foundEntry.count;
}
return foundEntry;
}
The function e() isn't returning anything; the inner anonymous function is returning its e value but that return value is being ignored by the caller (the caller being function e() (and can the multiple uses of 'e' get any more confusing?))
Because
function(e) {
return e;
}
is a callback. Array.forEach most likely calls it in this fashion:
function forEach(callback) {
for(i;i<length;i++) {
item = arr[i];
callback.call(context, item, i, etc.)
}
}
so the call back is called, but the return doesn't go anywhere. If callback were called like:
return callback.call();
the it would return out of forEach on the first item in the array.
You can use for...of to loop over iterable objects, like array, string, map, set... as per Mozilla docs.
const yourArray = [1, 2, 3]
for (const el of yourArray) { // or yourMap, Set, String etc..
if (el === 2) {
return "something"; // this will break the loop
}
}