Weird issue on Jquery .each function - javascript

I have a weird issue in my codes
I have something like
var test, result;
$(".class td").each(function(){
test = $(this).find('input').attr('size');
if(test){
result = test * 10;
}
console.log(result);
})
not every td has a input fields so test could be undefined. However, the console will always output a value from the test after test is defined.
For example:
undefined (test = undefined)
undefined (test = undefined)
undefined (test = undefined)
200 (test = 20)
200 (test = undefined)
200 (test = undefined)
200 (test = undefined)
I am not sure what's going on here. Can someone help me out? Thanks.

Define result in the inner scope rather than holding it in the outer scope, since the first result has value your further iterations still holds the old value and that is what you see.
$(".class td").each(function(){
var result ,
test = $(this).find('input').attr('size');
if(test){ //remove this check and you will see NaN for the iterations where test = undefined in your code
result = test * 10;
}
console.log(result);
});
You can also avoid looping the td that doesn't have input fields.
$(".class td:has(input)").each(...
or
$(".class td:has(input[size])").each(...

You could just grab the inputs in the selector, and map the result of each item to an array:
var result = $('.class td input').map(function() {
return $(this).attr('size') * 10;
}).toArray();

Related

jquery make alert equal to an array of names

This code above looks to see if my check boxes are checked or unchecked. IF they are unchecked then it logs in the console the names of the checkboxes that are unchecked. I want to take those names and put them in the alert box and am struggling to access the element.name outside the each loop. Anyone have any ideas?
// when page is ready
jQuery("#user_price_accept").submit(function(event) {
// on form submit
event.preventDefault();
var test = jQuery(this).find('input[type=checkbox]:not(:checked)')
var test2 = '';
test.each((i, element) => {
console.log(element.name)
test2 = element.name;
})
return test2;
if (test.length > 0) {
alert(test2);
}
});
jQuery has a handy .map() method which you can use to transform a collection of elements into an array of data.
You could then join that array into a string and alert it
jQuery("#user_price_accept").on("submit", function(event) {
event.preventDefault()
const test = jQuery(this).find('input[type=checkbox]:not(:checked)')
const names = test.map((_, el) => el.name).get() // get() returns the underlying array
if (names.length) {
alert(names.join(", "))
}
})
First, you're returning before the alert. That will stop execution of anything in the same bracket that occurs after that.
Second, you're reassigning test2 inside of your loop. Even if you can access it outside of the loop, all you're going to get is the name of the last element. Try using test2 += ', ' + element.name
Third, this bit here:
if (test.length > 0) {
alert(test2);
}
looks like you are checking the length of an unchanged list. Except the test you defined above is another jQuery object (which I'm not sure has a length built-in, but I digress). Still unchanged though. If this is what you are looking for, that's fine, but I would put the test.each((... inside of the if statment
You are missing concatenation of name and every time test2 gets replaced with a new name. Also returning test2 in function will go outside of function and alert code will not be executed. I have modified few lines
test2 += element.name; // names are added in test 2
return test2; // remove this line or handle after alert code
// when page is ready
jQuery("#user_price_accept").submit(function(event) {
// on form submit
event.preventDefault();
var test = jQuery(this).find('input[type=checkbox]:not(:checked)')
var test2 = '';
test.each((i, element) => {
console.log(element.name)
test2 += "," + element.name;
})
//return test2;
if (test.length > 0) {
alert(test2);
}
});

check if array has the user inputted value

I am using an input field to put user inputs in an array.
I want to check if the user inputted number is already in the array or not. And if it is in the array then the input should not be re-added.
Here is my attempt.
if(e.keyCode === 43){
var num = document.getElementById("numbers").value;
var oks = [];
// set num
// check if num is in the oks array
if( oks[num]==num ){
alert("It is already there.");
}
else{
oks[num.value]=num.value;
}
console.log(oks.value);
}
With the above code it says undefined in the console log.
Please help me find where I am wrong in this.
Thanks a lot :)
Your code has lots of mistakes, such as :
var oks = [];
The above is saying that every time the user inputs something, the array is empty, therefore there is nothing there, therefore the value is not there, so there is no use of trying to know whether the value exists or not, because it doesn't, so you should declare the oks variable outside of the eventListener.
oks[num]
The above is not the value, it's the element in the array whose index is the value, which are very different.
num.value
The above is a syntax error, because the num variable is a number not a dom element that has a value attribute.
And here's the solution to your problem :
if( oks.indexOf(num)>-1 ){
alert("It is already there.");
}
else{
oks.push(num);
}
you can do
if(oks.indexOf(num) != -1)
to check whether it lies in the array or not or alternatively you could use oks as an object and check if a fiels of a similar value is defined or not, which should be more efficient
var oks = [];
is being initialised on every request, hence it is always empty, initialise it at a parent/global scope, you should use
var oks = {};
// at a parent scope
if(e.keyCode === 43){
var num = document.getElementById("numbers").value;
// set num
// check if num is in the oks array
if( oks{num} != undefined ){
alert("It is already there.");
}
else{
oks[num]=true;
}
console.log(oks.num);
}

logic error in javascript code

I am trying to write some logic that will check for the existence of a specific record in two tables.
If the row exists in either table, I want to return TRUE.
For table A, when the record is added to the table, the id field looks like "123".
For table B, the same record would have the id of "a123". However, the value i have to search for the record is "row_123".
This is what my code looks like right now :
var checkForDuplicates = function(row_id) {
return !!($('#existing_members').find('#' + row_id.replace('row_','')).length || $('#selected_users').find('#' + row_id.replace('row_','a').length) );
};
I want the function to return true if the record exists in either table.
However, this statement returns true in cases when it should be false.
What I've tried so Far
I've been playing around in the console to make sure that my logic is correct:
!!(1 || 0) //returns true
!!(0 || 0) //returns false
!!(0 || 1) //returns true
I'm also currently reviewing the replace statements to make sure the find() is being supplied the right strings.
But a second pair of eyes to confirm that my logic is correct would be appreciated.
Thanks
EDIT 1
The solution, using Max's suggestion would be:
var checkForDuplicates = function(row_id) {
var parts = row_id.split('_');
var tableB = '#a'+ parts[1];
var tableA = '#' + parts[1];
return !!($('#existing_members').find(tableA).length || $('#selected_users').find(tableB).length);
}
However, as Ankit points out, I just had a typo in my original code. So this would be my final answer / solution:
var checkForDuplicates(row_id) {
return !!( $('#existing_members').find('#' + row_id.replace('row_', '')).length || $('#selected_users').find('#' + row_id.replace('row_','a')).length);
}
Your code has a typo at the end of return statement
...'a').length)); //it returns object which always evaluates to true
it should be
...'a')).length);
DEMO
var checkforduplicates = function(row_id){
//row_id looks like "row_123"
return !!($('#tableA').find('#' + row_id.replace('row_','')).length || $('#tableB').find('#' + row_id.replace('row_','a')).length );
}
alert(checkforduplicates("row_123"));
<table id=tableA><tr><td id="123">123 ID</td></tr></table>
<table id=tableA><tr><td id="a13">a13 ID</td></tr></table>
Corrected few issues to make the code more efficient:
var checkforduplicates = function(row_id) {
var id = row_id.split('_')[1]; // [ 'row', '123']
return $('#'+id).length || $('#a'+id).length;
}
No need for !! as operator || produces boolean result (true or
false)
Used $('#'+id) as more efficient jQuery selector
Removed unnecessary find(..) call
Eliminated unnecessary parenthesis (which had an issue)
I want the function to return true if the record exists in either table.
var checkForDuplicates = function(row_id) {
row_id = row_id.substring(4); // 'row_123' -> '123'
var table_A_row_id = row_id;
var table_A_row_exists = $('#tableA').find('#' + table_A_row_id).length > 0;
var table_B_row_id = 'a' + row_id;
var table_B_row_exists = $('#tableB').find('#' + table_B_row_id).length > 0;
return table_A_row_exists || table_B_row_exists;
};
of course it is returning the opposite of the things you want, cause you are using !!.
! is used to negotiate the return value of the specific function/variable e.g.:
if(!var_x == false)
this example only works if var_x is true.
So please be aware to avoid !! ;)
Please use a single ! instead!

show/hide div based on form value

var test = document.getElementById("TEST1").value;
if (test.value != 1) {
document.getElementById("field_DOPT").style.display='none';
}
This doesn't seem to work. I am getting the TEST1 value as 1 but its not hiding the div. Any help will be appreciated. thank you
In your case test is the value of the input element TEST1, it doesn't have a value property
so either assign the element as the value to test then use test.value in your condition
var test = document.getElementById("TEST1");
if (test.value != 1) {
document.getElementById("field_DOPT").style.display='none';
}
or use just test in the condition
var test = document.getElementById("TEST1").value;
if (test != 1) {
document.getElementById("field_DOPT").style.display='none';
}
You have assigned TEST1 value to the test variable, so in test you have do:
if (test != 1) {
document.getElementById("field_DOPT").style.display='none';
}
You already get the value property of your element when you define test, and then you look for the value property of its value property - so the simplest way to improve this code is:
var testValue = document.getElementById("TEST1").value;
if (testValue != 1) {
document.getElementById("field_DOPT").style.display='none';
}
I've changed your variable name from test to testValue so that it's clear that you are not actually dealing with the TEST1 element but instead with its value (so that it is clear there is no need to get the value property.

javascript not removing undefined objects from array

I've got an in page text search using JS, which is here:
$.fn.eoTextSearch = function(pat) {
var out = []
var textNodes = function(n) {
if (!window['Node']) {
window.Node = new Object();
Node.ELEMENT_NODE = 1;
Node.ATTRIBUTE_NODE = 2;
Node.TEXT_NODE = 3;
Node.CDATA_SECTION_NODE = 4;
Node.ENTITY_REFERENCE_NODE = 5;
Node.ENTITY_NODE = 6;
Node.PROCESSING_INSTRUCTION_NODE = 7;
Node.COMMENT_NODE = 8;
Node.DOCUMENT_NODE = 9;
Node.DOCUMENT_TYPE_NODE = 10;
Node.DOCUMENT_FRAGMENT_NODE = 11;
Node.NOTATION_NODE = 12;
}
if (n.nodeType == Node.TEXT_NODE) {
var t = typeof pat == 'string' ?
n.nodeValue.indexOf(pat) != -1 :
pat.test(n.nodeValue);
if (t) {
out.push(n.parentNode)
}
}
else {
$.each(n.childNodes, function(a, b) {
textNodes(b)
})
}
}
this.each(function() {
textNodes(this)
})
return out
};
And I've got the ability to hide columns and rows in a table. When I submit a search and get the highlighted results, there would be in this case, the array length of the text nodes found would be 6, but there would only be 3 highlighted on the page. When you output the array to the console you get this:
So you get the 3 tags which I was expecting, but you see that the array is actually consisting of a [span,undefined,span,undefined,undefined,span]. Thus giving me the length of 6.
<span>
<span>
<span>
[span, undefined, span, undefined, undefined, span]
I don't know why it's not stripping out all of the undefined text nodes when I do the check for them. Here's what I've got for the function.
performTextSearch = function(currentObj){
if($.trim(currentObj.val()).length > 0){
var n = $("body").eoTextSearch($.trim(currentObj.val())),
recordTitle = "matches",
arrayRecheck = new Array(),
genericElemArray = new Array()
if(n.length == 1){
recordTitle = "match"
}
//check to see if we need to do a recount on the array length.
//if it's more than 0, then they're doing a compare and we need to strip out all of the text nodes that don't have a visible parent.
if($(".rows:checked").length > 0){
$.each(n,function(i,currElem){
if($(currElem).length != 0 && typeof currElem != 'undefined'){
if($(currElem).closest("tr").is(":visible") || $(currElem).is(":visible")){
//remove the element from the array
console.log(currElem)
arrayRecheck[i] = currElem
}
}
})
}
if(arrayRecheck.length > 0){
genericElemArray.push(arrayRecheck)
console.log(arrayRecheck)
}
else{
genericElemArray.push(n)
}
genericElemArray = genericElemArray[0]
$("#recordCount").text(genericElemArray.length + " " +recordTitle)
$(".searchResults").show()
for(var i = 0; i < genericElemArray.length; ++i){
void($(genericElemArray[i]).addClass("yellowBkgd").addClass("highLighted"))
}
}
else{
$(".highLighted").css("background","none")
}
}
If you look at the code below "//check to see if we need to do a recount on the array length. ", you'll see where I'm stripping out the text nodes based off of the display and whether or not the object is defined. I'm checking the length instead of undefined because the typeof == undefined wasn't working at all for some reason. Apparently, things are still slipping by though.
Any idea why I'm still getting undefined objects in the array?
My apologies for such a big post!
Thanks in advance
I've modified your eoTextSearch() function to remove dependencies on global variables in exchange for closures:
$.fn.extend({
// helper function
// recurses into a DOM object and calls a custom function for every descendant
eachDescendant: function (callback) {
for (var i=0, j=this.length; i<j; i++) {
callback.call(this[i]);
$.fn.eachDescendant.call(this[i].childNodes, callback);
}
return this;
},
// your text search function, revised
eoTextSearch: function () {
var text = document.createTextNode("test").textContent
? "textContent" : "innerText";
// the "matches" function uses an out param instead of a return value
var matches = function (pat, outArray) {
var isRe = typeof pat.test == "function";
return function() {
if (this.nodeType != 3) return; // ...text nodes only
if (isRe && pat.test(this[text]) || this[text].indexOf(pat) > -1) {
outArray.push(this.parentNode);
}
}
};
// this is the function that will *actually* become eoTextSearch()
return function (stringOrPattern) {
var result = $(); // start with an empty jQuery object
this.eachDescendant( matches(stringOrPattern, result) );
return result;
}
}() // <- instant calling is important here
});
And then you can do something like this:
$("body").eoTextSearch("foo").filter(function () {
return $(this).closest("tr").is(":visible");
});
To remove unwanted elements from the search result. No "recounting the array length" necessary. Or you use each() directly and decide within what to do.
I cannot entirely get my head around your code, but the most likely issue is that you are removing items from the array, but not shrinking the array afterwards. Simply removing items will return you "undefined", and will not collapse the array.
I would suggest that you do one of the following:
Copy the array to a new array, but only copying those items that are not undefined
Only use those array items that are not undefined.
I hope this is something of a help.
Found the answer in another post.
Remove empty elements from an array in Javascript
Ended up using the answer's second option and it worked alright.

Categories

Resources