Avoid jquery function for all the content - javascript

I have a table with 20 rows. In each row there is an element
<p class="exp-date">'.$cust->Expiration_Date.'</p>
This element is going to be repeated and return different values but in a lot of rows return 0001-01-01.
I want to hide this content so I wrote this in javascript
var exp = $(".exp-date").val();
var exphide = '0001-01-01';
if(exp = exphide) {
$(".exp-date").html('');
}
and also have tried this
$('.exp-date').each(function() {
if(exp = exphide) {
$(".exp-date").html('');
}
});
But in both cases apply the jquery on the first row and modify everything not only where the statement is declared.
Someone any idea?
Thanks in advance

You're using assignment in if statement. The condition exp = exphide will always evaluate to true and the code inside the if statement will execute for all the elements.
Change
if(exp = exphide) {
to
if(exp == exphide) {
or
if(exp === exphide) {
Also, use text() instead of html() to get the date, and use trim() on it to remove extra spaces before comparing.
Use this/$(this) inside the each to get the innerText of the current element.
$('.exp-date').each(function () {
if ($(this).text().trim() == exphide) {
// ^^^^^^^^^^^^^^^^^^^^^^^^
$(this).html('');
// ^^^^
}
});

Use == and "this", else it will point to all classes. Code shown below
var exphide = '0001-01-01';
$('.exp-date').each(function() {
if(this.innerHTML == exphide) { //this.innerHTML
$(this).html(''); //this.html..else will point to all classes
}
});

First you should correct the syntax in the if condition and then try the below code. When you are using "each" for looping you should pass index and value to the callback function as shown below. Then you can achieve the desired result.
var exphide = '0001-01-01';
$('.exp-date').each(function(index, value) {
var exp = $(value).text();
if(exp == exphide) {
$(value).html('');
}
});
I suggest not to remove the content from table cell instead you can hide. Hope this helps.

Related

How does the matching JS code using indexOf work?

I've managed to copy some JS over into my doc, and I've got it working. But I don't entirely understand how its doing it.
It's a search function to match with data in a table and hide any rows that don't match.
But I don't understand the active line of code that actually searches and matches. Would someone explain it?
$('#searchBar').keyup(function() {
searchFunction($(this).val());
});
function searchFunction(value) {
$('#results tr').each(function() {
var found = 'false';
$(this).each(function() {
if ($(this).text().toLowerCase().indexOf(value.toLowerCase()) >= 0) {
found = 'true';
}
});
if (found === 'true') {
$(this).show();
} else {
$(this).hide();
}
})
};
It's this line I can't get my head around:
if ($(this).text().toLowerCase().indexOf(value.toLowerCase()) >= 0) {
found = 'true';
}
I understand how it changes the variable to true, but I don't understand how it matches the data in the Table row with the Value fed in.
It converts the value you sent to the function to lowercase, and then looks at the data in the row. It converts that to lowercase too, and sees if there is a match using indexof, which is covered here: How to use IndexOf in JQuery
Basically, the indexOf() method returns the position of the first occurrence of a specified value in a string. It returns -1 if the value to search does not occur.
Consider searching for "test"
var str = "Hello this is a test";
var n = str.indexOf("test");
The result of n will be: 16, ergo, as in your script, larger than 0... and "found"
What it does is
For each rows in my table "result"
If one of all these values, that I look in lowercase, is equal to what I typed in the "searchBar" in lower case, more than one time, then I found it, and so found = "true"
From search bar key press event will be triggered and value of search bar will passed to search function
$("#searchBar").keyup(function() {
searchFunction($(this).val());
});
function searchFunction(value) {
//value will contain the value of search bar
$("#results tr").each(function() {
//assuming value is not there in tr
var found = "false";
//now searching for each tr for value
$(this).each(function() {
//converting to lower case and comparing each value with searchbar value
if (
$(this)
.text()
.toLowerCase()
.indexOf(value.toLowerCase()) >= 0
) {
found = "true";
}
});
//actual showing/hiding row
if (found === "true") {
$(this).show();
} else {
$(this).hide();
}
});
}
if need more info about index of
https://www.w3schools.com/jsref/jsref_indexof.asp
#MattCouthon let me know if you need anything else

How to get a tr value within a filter

I having issues grabbing my data within a jquery filter. I have tried finding a solution but haven't been able to find one. I am fairly new with Jquery so I believe this might be a trivial answer.
I like to loop through my array checking it against the cells value, How do I fetch the cells current value / (this) value?
EDIT: Thanks for the help, final solution as follows. Where datesToSearchFor is an array of string dates and nth-child(2) is my dates column in my table.
$("#UnfinishedTable tr").filter(function () {
if (this.id !== 'headerRow') {
var isItThere = false;
var data = $(this).find("td:nth-child(2)").html();//my dates column
datesToSearchFor.forEach(function (entry) {
if (data == entry) {against are array of dates
isItThere = true;
}
});
}
if (isItThere) {//if one was found show the row else hide it
$(this).show()
}
else {
if (this.id !== 'headerRow') {
$(this).hide()
}
}
});
$('#unfinishedTable tr').not('#headerRow').each(function(){
var val = $(this).attr('value');
var src = datesToSearchFor.find(function(n){return n == val;});
$(this).css({'display' : src == null ? 'none' : ''});
});
Filtering is for finding your elements, not acting upon them. After you .filter(), you should put your logic into .each()
$('#UnfinishedTable tr')
.not('#headerRow')
.each(function () {
... // logic
$(this).show();
});
The above example uses .not() as that is closer to what your desired logic is.
The above code seems to be correct, does the console return any errors? Is datesToSearchFor a string vector? Is headerRow the id you assigned to the header tr to ignore it?

Including a for loop in an if statement

I'm building an application in which I want to display some errors when a user enters invalid values in an input box. A correct value is appended as 'entry' to a div if no errors were found. In total there are 3 cases when to display errors:
The input value is empty
The input value is a number
The input value already exists
These errors are displayed with if else statements.
1.and 2. were easy, but the problem case (3.) only validates against the first element of class .cat_entry.
if(cat_input == '') { // generate errors
errorDisplay(error_input_empty);
} else if(!isNaN(cat_input)) {
errorDisplay(error_input_number);
} else if($('.cat_entry') == cat_input) { // THIS IS THE PROBLEMATIC LINE
// .cat_entry is the class of the entries that have been appended
errorDisplay(error_duplicate);
} else {
// stuff
};
So I believe I need a for loop/ .each() (no problem so far), but how do I include this as a condition in an if statement? Something like.. if( for(i=0;i<$('.cat_entry').length;i++) { ... }; ... How to return true (or something similar) when one of the entries matches the input value, then pass the return value to the if statement?
EDIT: here is a jsFiddle with the relevant code. I updated it with $.inArray() method. I'd like to try and use this instead of a for / .each() loop.
You can try this:
var a=$('.cat_entry'),o={};
for(i=0;i<a.length;i++) {
var s=a[i].val();
if(s in o){
errorDisplay(error_duplicate);
return;
}
o[s]=true;
}
or
var o={};
$('.cat_entry').each(function(){
var s=$(this).val();
if(s in o){
errorDisplay(error_duplicate);
return;
}
o[s]=true;
}
You can actually use the jQuery inArray function for this, such as:
else if($.inArray(cat_input, $('.cat_entry') != -1)
}
The solution was to add this to the function:
var isDuplicate = false;
$('.cat_entry').each(function() {
if(!$(this).text().indexOf(cat_input)) {
isDuplicate = true;
}
// And in the if else loop:
else if(isDuplicate == true)
//and just before the function ends
isDuplicate = false;
Thanks to all for the help you offered.

jquery each loop only looping once and if using else code stops

I've got two problems with the following javascript and jquery code.
The jquery each loop only iterates once, it gets the first element with the right ID does what it needs to do and stops.
The second problems is that when I use the else in the code the one inside the each function, it doesn't even tries the next if, it just exits there.
I'm probably doing something fundamental wrong, but from the jquery each function and what I'd expect from an else, I don't see it.
Javascript code:
var $checkVal;
var $checkFailed;
$("#compliance").live("keypress", function (e) {
if (e.which == 10 || e.which == 13) {
var checkID = $(this).parents('td').next().attr('id');
var checkVal = $(this).val();
$('#' + checkID).each(function () {
var cellVal = $(this).text();
if (checkVal == cellVal) {
$(this).removeClass("compFail").addClass("compOk");
} else {
$(this).removeClass("compOk").addClass("compFail");
var checkFailed = True;
}
});
if (checkFailed == 'True') {
(this).addClass("compFail");
} else {
(this).addClass("compOk");
}
}
});
How could I get the each loop to iterate through all instances of each element with the id assigned to the variable checkID, and get the code to continue after the else, so it can do the last if?
An id should appear on a page only once. If you want to have multiple elements with same id, then use a class, not an id.
Your each loop iter only once because you are selecting by id thus you are selecting only one element in the page. If you change you elements to a class it should work like you expect.
This is to illustrate what I'm talking about in my comment, so that you do not remove the wrong var:
var checkVal;
var checkFailed;
$("#compliance").live("keypress", function (e) {
if (e.which == 10 || e.which == 13) {
var checkID = $(this).parents('td').next().attr('id');
//HERE is the first edit
checkVal = $(this).val();
$('#' + checkID).each(function () {
var cellVal = $(this).text();
if (checkVal == cellVal) {
$(this).removeClass("compFail").addClass("compOk");
} else {
$(this).removeClass("compOk").addClass("compFail");
//HERE is the second
checkFailed = True;
}
});
if (checkFailed == 'True') {
(this).addClass("compFail");
} else {
(this).addClass("compOk");
}
}
});
Normally, the way you have it would cause a compile-time error (in a typed language like C#) for redeclaring a variable. Here, it's not clear to me if it will be used as a local variable (ignoring your global variable) or if javascript will combine them and consider them the same. Either way, you should use it as I have shown so that your intent is more clear.
EDIT: I have removed the $ from your variables (var $checkVal) as on jsFiddle it was causing issues. SO if you do not need those $'s, then remove them. Also, note that testing on jsFiddle indicates that you do not need to change your code (other than possibly removing the $ from your declaration) as javascript appears to consider them the same variable, despite the redeclaration, which I find a bit suprising tbh.
The jquery each loop only iterates once, it gets the first element
with the right ID does what it needs to do and stops.
Yes, this is absolutely right for the code you're using:
$('#' + checkID).each(function(){};)
ID attributes are unique. There must be only one element with a given ID in the DOM. Your selector can match only one element. You are iterating over a collection containing just 1 item.

In Javascript or jQuery, how do I detect if a specific tag exists or not?

Given the following strings:
htmlStr1 = "<img>test1</img>";
htmlStr2 = "<div>test2</div>";
I'd like to know if there's a way to write a function just to detect for the "img" tag (for example). So if both of these strings are passed to it, and it should not do anything if the 2nd string is passed to it.
so for example, you'd run a function like:
result1 = checkIfTagExists(htmlStr1, "img");
result2 = checkIfTagExists(htmlStr2, "img");
alert(result1); // should output "true" or "1" or whatever
alert(result2); // should output "false" or do nothing
I would use a speedy RegExp for this, no need to use any jQuery selectors when not needed.
function checkIfTagExists(str, tag) {
return new RegExp('<'+tag+'[^>]*>','g').test(str);
}
If this is more of an example of functionality you are looking for and not the exact situation you'd use it in, the jQuery has selector may be helpful.
Related question with example.
For this situation you would do:
var str1ContainsImg = $(htmlStr1 + ":has(img)").length > 1;
var str2ContainsImg = $(htmlStr2 + ":has(img)").length > 1;
Edit: As tvanfosson pointed out in the comments, if your img tag doesn't have a closing tag ( <img src='' /> ),this exact solution wouldn't work. If that's an issue, you can check the tag name of the first element returned like this:
var htmlStr3 = "<img src='' />";
var containsEmptyImg = $(htmlStr3 + ":has(img)").length > 1 ||
$(htmlStr3 + ":has(img)")[0].tagName.toUpperCase() == 'IMG';
Wrap this in an if statement and you are good to go
jQuery(jQuery(htmlStr1)).find('img').size() > 0
This will be easier if the strings are in the innerHTML of an element:
function checkIfTagExists(element, tagName) {
return element.getElementsByTagName(tagName).length > 0;
}
A regex check would probably be insufficient (see RegEx match open tags except XHTML self-contained tags) :)
If you really do just have the strings, you can create an element from the string, and set the innerHTML to the string, then do the above check on that new element. This is what the $(tagName, htmlContext) would be doing.
This might have a bit of overhead, but it should be robust enough for use with any given string or the innerHTML of any element.
function getTagCountFromString(string, tag) {
var count = 0;
tag = tag.toLowerCase();
$(string).each(function(idx, el){
if(el.nodeType === 1) {
if(el.tagName && el.tagName.toLowerCase() === tag) {
count++;
}
if(el.childNodes.length > 0) {
try {
count += getTagCountFromString(el.innerHTML, tag);
} catch (ex) { }
}
}
});
return count;
}
getTagCountFromString('<img src=""/><a href=""/>', 'img'); //returns 1
Then to get a boolean value you could check if the count is not equal to 0 or make a helper function which does it for you.
in straight javascript:
function checkIfTagExists(src, tag) {
var re = "<"+tag + ">\.+<\\/"+tag+">";
return new RegExp(re).test(src);
}

Categories