I recently met a problem with .not() function, this is the code:
var interval = setInterval(function() {
$('.test').not('.updated').each(function(){
var $parentDiv = $('.test').parent('div');
// do something
parentDiv.find('.test').addClass("updated");
//Above: change this element's status
});
}, 3000);
Problem is:
Sometimes when the element $('.test') who has class 'updated' also within the loop.
What I think:
it means the not() selector not working?
So I would like to know what is REALLY the problem of the code?
Your code is finding all the elements with class "test", and then excluding those that also have the class "updated".
Then, for each of those elements, you're doing another .find() operation to find elements with class "test". That, however, does not include the .not() call, so if you have an element with class "test" nested inside another one, it will be affected whether or not it already has class "updated".
I think your code really should just be like this:
var interval = setInterval(function() {
$('.test').not('.updated').addClass("updated");
}, 3000);
You don't need the .each() because .addClass() will do that for you.
edit — if you do need to do more work inside a .each(), your code would look like this:
var interval = setInterval(function() {
$('.test').not('.updated').each(function(){
var $parentDiv = $(this).parent('div');
// do something
$(this).addClass("updated");
//Above: change this element's status
});
}, 3000);
Inside the .each() callback, this will be bound to each of the selected elements from the outer jQuery sequence: the set of elements that have class "test" but not class "updated". If you use $(".test") again inside the .each() callback, that will start all over again and find all the elements with class "test" in the entire page.
Here is your updated function which should work use $(this) instead of $('.test') inside the each loop
var interval = setInterval(function() {
$('.test').not('.updated').each(function(){
var $parentDiv = $(this).parent('div');
// do something
$(this).addClass("updated");
//Above: change this element's status
});
}, 3000);
As you are referencing in the each $('.test') which is all the test class .updated or otherwise that is the reason the .updated class is still coming up in the loop
You are using .find() which is used to select all descendants of that element.
Refer .find()
Therefore, in your case, the scenario is class .test without class .updated will search in all its children to find class .test and it will add class updated to it. So, all the children whether or not they are having class .updated, .updated class will be added to it.
Hence, what you want to do can be simply achieved by this:
$('.test').not('.updated').each(function(){
$(this).addClass("updated");
});
or why not simply,
$('.test').not('.updated').addClass('updated');
Related
I need some help with creating a loop in this jQuery function. I have some elements on my HTML page with the attribute [level-data="l1"], and I use them in my function to make some changes on the page. I have 12 different attributes starting with the [level-data="l1"] and finishing with the [level-data="l12"]. What I want is to create a jQuery loop instead of copying this function over and over for 12 times, each element will have a different [level-data='ln'] attribute, where n is a number from 1 to 12.
Here is my code:
$('.chart-level[level-data="l1"]').on("click", function () {
$('.chart-level').removeClass('active');
$('.chart-levels-items .level-info').removeClass('active');
$(this).addClass('active');
$('.chart-levels-items .level-info[level-data="l1"]').addClass('active');
$('.chart-slider-item.page_slider').removeClass('shown');
$('.chart-slider-item.page_slider[level-data="l1"]').addClass('shown');
$('.chart-slider-item.popup_slider').removeClass('shown');
$('.chart-slider-item.popup_slider[level-data="l1"]').addClass('shown');
if(window.matchMedia('(max-width: 768px)').matches){
$([document.documentElement, document.body]).animate({
scrollTop: $(".chart-levels-items .level-info[level-data='l1']").offset().top
}, 2000);
}
});
Thank you in advance!
You don't need a loop. Use .chart-level[level-data] as the selector and read the level-data attribute of the clicked element. [...] is an attribute selector which selects elements that have a certain attribute.
Note that level-data is an invalid attribute. You can use data-* attributes instead. i.e. change it to data-level. Then you can use $(this).data('level') for reading the value of the data-level attribute.
$('.chart-level[data-level]').on("click", function () {
var level = $(this).data('level')
$('.chart-levels-items .level-info[data-level="' + level + '"]').addClass('active');
// ...
});
In case that you are using the attribute just for selecting related elements to the clicked element, then you should consider using jQuery traversal methods (like parent, siblings, ...) for selecting the target elements instead.
I want to do something like:
if($(this).hasClass("playButton"))
{
$(this).find("li").removeClass("active");
}
But instead of "this" in "if" statement I want to use any class selector. But I don't know how to get concrete DOM element, which corresponds to the condition.
So I need:
if($(.anyClass).hasClass("playButton"))
{
$(current element, which corresponds to
if condition).find("li").removeClass("active");
}
$(".playButton li").removeClass("active");
...?
You can select the elements using the ".anyClass" selector and then iterate through them using each. In the callback function of each, this will refer to the current DOM element.
$(".anyClass").each(function() {
if ($(this).hasClass("playButton")) {
$(this).find(".btn").removeClass("playButton");
}
});
However, for this particular scenario, you can reach your goal without using each. Simply target the element directly and manipulate it, as #Derek朕會功夫 suggested in his answer.
$(".playButton li").removeClass("active");
I try to add CSS class to <li> element, when I click on the button but addClass not working.
Here is my JS:
$('.test').click(function(event) {
var centrum1 = $('.p17');
$('section.bok-map').find( centrum1 ).addClass('active-region');
});
And this how is looking HTML code:
Where is the problem? find() returns true.
Here is demo: http://demo.vrs-factory.pl/mapDemo/
You had a couple of errors, as you were not selecting the correct element, hence the length of the selector was 0.
Firstly, the class is called pl7 not p17 and secondly, when using removeClass you don't put the . before the name of the class. As you are using removeClass it is understood that you want to target a class, hence not requiring you to specify this by adding the dot.
<script>
var centrum1 = $('.pl7');
$('.test').click(function(event) {
$('section.bok-map').find( centrum1 ).removeClass('pl7');
});
</script>
Also, it may be worth noting that since you are only referencing$(.pl7) once you do not necessarily have to assign it to a variable. You could also write it as below. It is up to you.
$('.test').click(function(event) {
$('section.bok-map').find('.pl7').removeClass('pl7');
});
This is my script
var newclass = 0;
jQuery("#addexperience").click(function(){
$("#expclone").clone().find("input:text").val("").end().prependTo( ".exp_clone" );
$(".ongoing").each(function(){
$(".ongoing").addClass("newclass"+newclass);
newclass++;
});
});
I am tring to clonning a perticular div, and add an class on clone element.
but addClass append every time,
means in first clone it added: newclass1, in second clone it added: newclass1 newclass2; so on..
i want only newclass2 in second clone, and newclass3 in thire clone and so on..
Try this,
var newclass = 0;
jQuery("#addexperience").click(function(){
$clone=$("#expclone").clone()
$clone.find("input:text").val("");
$clone.find(".ongoing").removeAttr('class') // remove all classes
.addClass('ongoing'); // again add ongoing class
$clone.find(".ongoing").each(function(){
$(this).addClass("newclass"+newclass);
newclass++;
});
$clone.prependTo(".exp_clone");
});
But, is is better to give an new id instead of new class.
You should use $(this) inside the callback of .each:
$(".ongoing").each(function(){
$(this).addClass("newclass"+newclass);
newclass++;
});
Or you even don't need the variable newclass, .addClass accept a function as parameter:
$(".ongoing").addClass(function(index) {
// index is start from 0
return "newclass" + (index + 1);
});
This is because every time you clone an element, it's going to add the class to each of those elements even though it is already present. What you do is, once you clone the element, get the last cloned element and addClass only for that. Remove the .each() function and try:
$(".ongoing").last().addClass('newClass'+newclass);
newclass++;
change this line:
$(".ongoing").addClass("newclass"+newclass);
to:
$(".ongoing").removeClass().addClass("newclass"+newclass);
it will remove all previous classes of .ongoing and add new class in it.
if you want to have .ongoing class then try like this:
$(".ongoing").removeClass().addClass("ongoing newclass"+newclass);
Here's how I append the value:
$('<div>someText</div>').appendTo(self);
And here's how I want to remove it:
$(self).remove('<div>someText</div>');
The appending works, the removing doesnt. What am I doing wrong?
The .remove() function takes a selector to filter the already matched elements, not to match elements inside of them. What you want is something like this:
$(self).find('div:contains(someText)').remove();
That will find a <div> element containing the text someText inside of whatever element self is, then removes it.
The API http://api.jquery.com/remove/ sais that a selector is required.
Try $(self).remove('> div');
This will remove the first childs of div.
You can use $(self).filter('div:contains("someText")').remove(); to remove a div with a specific content or $(self).find('> div').remove(); to remove the first childs of div.
EDIT: removed first version I posted without testing.
It most likely has to do with the scope of self. Since you've named it self I am assuming that you are getting this variable using $(this) on the click event. If that's the case, and you want to call the remove method, you can only do so from within the same function. Otherwise you need to either store the element in a variable or provide another selector to access it.
Example:
<div class="div1"></div>
this will be the div with the click event
$(document).ready(function(){
var self = null;
$('.div1').click(function(e){
self = $(this);
var itemToAdd = '<div>SomeText</div>';
$(itemToAdd).appendTo(self);
});
// to remove it
// this will remove the text immediately after it's placed
// this call needs to be wrapped in a function called on another event
$('.div1').find('div:contains(someText)').remove();
});