How to phrase 'has not' in jquery? - javascript

For a page in our app there is a certain number of customers that are generated in a list when the page is loaded. As one scrolls down on this page more customers are generated towards the bottom of the list, and so forth till one scrolls all the way down and there are no more customers to generate.
I am trying to check, within an .on() function, if the new generated customers at the bottom has a clock icon, and if not then to add a clock icon to the new customers. This is my check:
var isClock = $(timepickers).parent().has('.clockIcon').length ? '' : addClock;
if (typeof isClock === 'function') {
isClock();
}
The problem is that the customers that were originally there to start with on the page, of course have the clock icon, so because some of the customers have a clock icon its not adding it to any of the ones that don't have one now. The .has() makes more since, but I like the idea of the .is() because of what it says on the jquery website:
Check the current matched set of elements against a selector, element, or jQuery object and return true IF AT LEAST ONE of these elements matches the given arguments.
And thats what I needed for it to check if ANY of the customers don't have the clock icon then to add it. I cannot think of way to use the .is() so instead I am thinking to use the .not() or not: to see if any of the customers don't have the clock icon then run the function. But I am not sure how to say 'if something does not have something' not 'if something is not something'. Anyone know how to do this????

Use not() instead of has()

Just negate the expression?
var isClock = ( ! $(timepickers).parent().has('.clockIcon').length ) ) ? '' : addClock;

first thing i thought of, was http://api.jquery.com/attribute-contains-word-selector/
$(timepickers).parent().find('class=~"clockIcon"').length ? '' : addClock;
but it might not even be the simplest for your case

While not too pretty (I don't know jQuery) this would fire the event if the elements with the icon doesn't equal the total amount of elements
var isClock = $(timepickers).parent().has('.clockIcon').length == $(timepickers).length ? "" : addClock;
if (typeof isClock === 'function') {
isClock();
}
That being said, I'm sure there is a concise way to do this with proper jQuery

See jQuery .not(). Also use .each that way you can go over each item's parent and check it individually:
$(timepickers).each(function () {
// If the parent doesn't have clockIcon then add it
if (!$(this).parent().hasClass('clockIcon')) {
addClock();
}
});

Related

JavaScript beginner, if a variable does not match to do something

Basically what I'm trying to do is write a greasemonkey script so that if a link on a page is not a link I have on an ignore list to just open the link, if it is on the list then reload the page after 5 seconds here is what I tried so far
var url1 = $("span.capsulelink a:eq(0) ").attr("href");
var ignoreList = ["example1.com","example2.com"]
if (url1 !== ignoreList) {
window.open(url1);
} else {
setTimeout(function() {
location.reload();
},5000);
}
I know it's the (url1 !== ignoreList) part I am having trouble with, I just can not seem to find the right expression for that. Like I do not know how to say if url1 is not on the ignoreList {do something}.
ignoreList.indexOf(url1) !== -1
This is another way of saying "is url contained in the ignoreList array?"
This is because the indexOf() method of Array returns the index of the element you're looking for, or -1 if the element doesn't exist.
To negate this, which is what you want to do, you write:
ignoreList.indexOf(url1) === -1
(i.e. is url1 not in ignoreList?)
This is a good question, because the answer really isn't intuitive.
When you're starting to learn javascript, some of the syntax patterns begin to look familiar.
But the javascript equivalent of PHP's
if (!in_array([ARRAY]));
simply isn't obvious at all - this is one syntax you just need to know.
Here is the javascript you're looking for:
if (ignoreList.indexOf(url1) !== -1) {
[RELOAD PAGE CODE HERE]
}
else {
[OPEN THE LINK CODE HERE]
}
Here's why it works:
ignoreList.indexOf([VALUE]) looks through the ignoreList array and searches through the array's items.
If one of those items is [VALUE], it returns the index of that item.
Importantly, if none of the items are [VALUE] it returns -1.
So, in order to establish that at least one of the items is [VALUE], you have to verify that the returned index definitely isn't -1.
Consequently the condition you need to check for is:
if (ignoreList.indexOf(url1) !== -1)

Easy level, selecting elements in DOM, optimization, creating method function

Please, do not laugh, too much. I know jQuery ans JS for a short a while.
1) How can I make this code more efficient? First line is how do I "select" elements, the second, line is how do I prep to "select", next or previous element.
jQuery('code:lt('+((aktywneZdanie+1).toString())+'):gt('+((aktywneZdanie-1).toString())+')').removeClass('class2');}
aktywneZdanie=aktywneZdanie-1
2) I can not create a function which is working as a method. What I meant is how to change:
jQuery('#something').addClass('class1')
.removeClass('class2');
to something like this:
jQuery('#something').changeClasses();
function changeClasses(){
.addclass('class1');
.removeClass('class2');}
For the first one, why do you need a selector like that? couldn't you find something less specific to hook onto? If you must keep it when joining an number and a string, JavaScript will convert the number to string behind the scenes so you don't really need the .toString() and could do the "maths" +/-1 outside of your selector making it more readable.
Edit
In regards to your comment I am not really sure what you mean, you could assign a class to the "post" items and then add the unique id to a data-attribute ID. To make it simpler you could do something like this:
var codeLt = aktywneZdanie + 1,
codeGt = aktywneZdanie - 1;
$('code:lt(' + codeLt + '):gt(' + codeGt +')').removeClass('class2');
End Edit
And the second solution should work, all your doing is passing the dom elements found from your selector into a function as a jQuery "array" in which manipulate to your needs
And for your second question why not just toggle the class on and off? having a default state which reflects class one?
jQuery('#something').toggleClass('uberClass');
Or you can pass your selector to the function
changeClasses(jQuery('#something'));
Then inside you function work on the return elements.
Edit
Your code should work fine, but id suggest checking to make sure you have got and element to work on:
changeClasses(jQuery('#something'));
function changeClasses($element){
if($element.length > 0) {
$element.addClass('class1');
}
}
End Edit
Hope it helps,
1) How can I make this code more efficient? First line is how do I "select" elements, the second, line is how do I prep to "select", next or previous element.
jQuery('code:lt('+((aktywneZdanie+1).toString())+'):gt('+((aktywneZdanie-1).toString())+')').removeClass('class2');}
aktywneZdanie=aktywneZdanie-1
I stoped creating this wierd code like this one above, instead I start using .slice() (do not forget to use .index() for arguments here), .prev(), .next(). Just those three and everything is faster and clearer. Just an example of it below. No it does not do anything logical.
var activeElem = jQuery('code:first');
var old Elem;
jQuery('code').slice('0',activeElem.index()).addClass('class1');
oldElem=activeElem;
activeElem=activeElem.next();
jQuery('code').slice(oldElem.index(),activeElem.index()).addClass('class1');
oldElem.toggleClass('class1');
activeElem.prev().toggleClass('class1');
and the second part
2) I can not create a function which is working as a method. What I meant is how to change:
jQuery('#something').addClass('class1')
.removeClass('class2');
to something like this:
jQuery('#something').changeClasses();
function changeClasses(){
.addclass('class1');
.removeClass('class2');}
This one is still unsolved by me.

Javascript taking too long to run

I have a script that is taking too long to run and that is causing me This error on ie : a script on this page is causing internet explorer to run slowly.
I have read other threads concerning this error and have learned that there is a way to by pass it by putting a time out after a certain number of iterations.
Can u help me apply a time out on the following function please ?
Basically each time i find a hidden imput of type submit or radio i want to remove and i have a lot of them . Please do not question why do i have a lots of hidden imputs. I did it bc i needed it just help me put a time out please so i wont have the JS error. Thank you
$('input:hidden').each(function(){
var name = $(this).attr('name');
if($("[name='"+name+"']").length >1){
if($(this).attr('type')!=='radio' && $(this).attr('type')!=='submit'){
$(this).remove();
}
}
});
One of the exemples i found : Bypassing IE's long-running script warning using setTimeout
You may want to add input to your jquery selector to filter out only input tags.
if($("input[name='"+name+"']").length >1){
Here's the same code optimised a bit without (yet) using setTimeout():
var $hidden = $('input:hidden'),
el;
for (var i = 0; i < $hidden.length; i++) {
el = $hidden[i];
if(el.type!=='radio' && el.type!=='submit'
&& $("[name='" + el.name + "']").length >1) {
$(el).remove();
}
}
Notice that now there is a maximum of three function calls per iteration, whereas the original code had up to ten function calls per iteration. There's no need for, say, $(this).attr('type') (two function calls) when you can just say this.type (no function calls).
Also, the .remove() only happens if three conditions are true, the two type tests and check for other elements of the same name. Do the type tests first, because they're quick, and only bother doing the slow check for other elements if the type part passes. (JS's && doesn't evaluate the right-hand operand if the left-hand one is falsy.)
Or with setTimeout():
var $hidden = $('input:hidden'),
i = 0,
el;
function doNext() {
if (i < $hidden.length) {
el = $hidden[i];
if(el.type!=='radio' && el.type!=='submit'
&& $("[name='" + el.name + "']").length >1) {
$(el).remove();
}
i++;
setTimeout(doNext, 0);
}
}
doNext();
You could improve either version by changing $("[name='" + el.name + "']") to specify a specific element type, e.g., if you are only doing inputs use $("input[name='" + el.name + "']"). Also you could limit by some container, e.g., if those inputs are all in a form or something.
It looks like the example you cited is exactly what you need. I think if you take your code and replace the while loop in the example (keep the if statement for checking the batch size), you're basically done. You just need the jQuery version of breaking out of a loop.
To risk stating the obvious; traversing through the DOM looking for matches to these CSS selectors is what's making your code slow. You can cut down the amount of work it's doing with a few simple tricks:
Are these fields inside a specific element? If so you can narrow the search by including that element in the selector.
e.g:
$('#container input:hidden').each(function(){
...
You can also narrow the number of fields that are checked for the name attribute
e.g:
if($("#container input[name='"+name+"']").length >1){
I'm also unclear why you're searching again with $("[name='"+name+"']").length >1once you've found the hidden element. You didn't explain that requirement. If you don't need that then you'll speed this up hugely by taking it out.
$('#container input:hidden').each(function(){
var name = $(this).attr('name');
if($(this).attr('type')!=='radio' && $(this).attr('type')!=='submit'){
$(this).remove();
}
});
If you do need it, and I'd be curious to know why, but the best approach might be to restructure the code so that it only checks the number of inputs for a given name once, and removes them all in one go.
Try this:
$("[type=hidden]").remove(); // at the place of each loop
It will take a short time to delete all hidden fields.
I hope it will help.
JSFiddle example

Show alert after all requirements have been met

I have a form where the user can 1.) check one option and be done. or 2.) check the other option and fill out a text field.
Whole thing is, after all is said and done I'd like for my alert to show, but it doesn't.
$('.know-your-role').show('fast', function() {
var $checkboxes = $('input:checkbox.checkchoice');
if($checkboxes.is(':checked')){
// show this after checked and the input has been filled.
alert('cool');
}else if($checkboxes.is(':checked') & $(".year").va() != "" ){
alert('cool');
}
});
How do I get the alert to show after all requirements (checkboxes and input) have been met?
I've made a fiddle here to show what I'm working with.
Thank you for your help in advance.
As well as the previous correct answers (missing & and misspelled val) there is a more fundamental logical issue here. You seem to have this structure:
if (conditionA) {
// behaviorA
} else if (conditionA && conditionB) {
// behaviorB
}
You will never reach behaviorB with such logic. If conditionA fails then conditionA && conditionB will certainly also fail.
Do you need to reverse the order of your if and else-if blocks?
Missing '&'
$checkboxes.is(':checked') && $(".year").val() != ""
You should use && instead of & for boolean comparisons, and also you appear to have mis-typed val as va.
I would suggest having two events, one on the 'Teacher' check box being checked and one on the year field being completed. Both events can trigger a single function that shows your alert and whatever other logic you want. So there is little duplication.
This helps to separate the events from the logic that shows/hides the year field and more easily allows you to perform different actions for the two events if that's a requirement.

jQuery filter method usage

What's the use of below snippet ? I extracted it from jQuery API. I don't understand it:
$("div").filter( $("#unique") )
Please be kind enough to explain this to me.
It is extracting the only one div with id=unique.
$('div'). // return all divs
filter( $('#unique') ); // take the div with id=unique
So. this statement will return you the div with id=unique.
Note
This statement can also be written as $('div#unique') or just $('#unique').
The filter method enables you to filter out only specific elements from amongst a selection. Say you want to choose all spans whose text contains more than 3 characters. So you would do this:
$("span").filter(function() { return $(this).text().length > 3; }).click(...);
The function should check for some condition and return a boolean. if it sends true that element is kept in the selection, else discarded. So for your current question, it would

Categories