Each function triggers only once - javascript

I'm trying to triggers a function on several owl-carousel sliders having the same class. If i do a console.log, it logs twice, but works only on the first slider.
Here's my function:
function setActiveItem(){
var item = $('.owl-item');
var itemLink = $('.owl-item a');
var pos = $('.is-active').parent().parent().index();
$('.slider-mobile').each(function() {
if($(this).find(itemLink).is('.is-active')) {
item.removeClass('active');
$(this).trigger('to.owl.carousel', [pos, 1, true]);
}
})
}
setActiveItem();
And here's a simplified version of my markup:
<ul class="list-container slider-mobile" data-stage-padding-items="200">
<li class="list-item">
item
</li>
</ul>
<ul class="slider-mobile" data-stage-padding-items="200">
<li class="list-item">
item
</li>
</ul>
I'm not sure if i'm using the each() function right, or if it fits my need at all.

Ok i figured it out.
#Reinder Wit you were right i was referencing the item of the first slider only, so both of my sliders were getting the same datas.
I did this:
function setActiveItem(){
$('.slider-mobile').each(function() {
var item = $(this).find('.owl-item');
var itemLink = $(this).find('.owl-item a');
var pos = $(this).find('.is-active').parent().parent().index();
if($(this).find(itemLink).is('.is-active')) {
item.removeClass('active');
$(this).trigger('to.owl.carousel', [pos, 1, true]);
console.log(pos);
}
})
}
setActiveItem();
And it is working now. Thanks for the clue.

You should activate your listener in the document ready like this:
$(document).ready(function(){
setActiveItem();
});

Related

Jquery Scroll to elements without Ids, only by data attributes

I want the page to scroll down to my "container"-li which wraps my current elements. The li doesn't have an id attribute and it can't have for HTML validation purposes. Each li has a data attribute named: data-commentid This attribute contains a GUID and is what i want to use when binding the scroll.
How do i scroll to a element only by using it's data-attribute?
var container = $("body").find(".roomWall.commentBox.publicListing:first");
var targets = $(container).find("li.commentInList.topLevelComment");
if ($.cookie('scrollTarget')) {
var cookieValue = $.cookie("scrollTarget").split('"');
var splittedStr = cookieValue[1];
$(targets).each(function () {
var $self = $(this);
if ($($self).attr("data-commentid") === splittedStr) {
var target = $("#" + splittedStr);
$($self).fadeOut("slow").hide().delay(500).queue(function (next) {
next();
}).delay(1000).queue(function (next) {
var $container = $("html,body");
$($container).animate({
scrollTop: $self.offset().top
}, 1000);
next();
}).delay(1000).queue(function () {
$($self).fadeIn(1000);
$(target).focus();
});
$.removeCookie("scrollTarget", { path: "/" });
}
});
}
The cookie contains the GUID I want. Inside my li ($self) there's a textarea with id={Some Guid} which, in this case refers to my $target variable. Since I didn't managed to get it working with $self.offset().top I added $scrollTo and tried with that one, which didn't work either.
Regarding to the Markup, It's pretty complex so I will only show you the parts we need, to prevent confusion. A wrapping li with the data-commentId:
Further down the hierarchy we have:
Hope someone can find out where my code breaks.
I would recommend using jQuery's filter() instead of trying to concatenate it in. I also think the $("html,body") part is where it's bugging out for you. Otherwise your code is actually correct:
var someGuid = "0003";
var $scrollTo = $("li.commentInList.topLevelComment").filter(function(i){
return $(this).data('commentid') === someGuid;
});
$(document.body).animate({
scrollTop: $scrollTo.offset().top
}, 1000);
li {
height: 10em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="commentInList topLevelComment" data-commentid="0001">Comment 1</li>
<li class="commentInList topLevelComment" data-commentid="0002">Comment 2</li>
<li class="commentInList topLevelComment" data-commentid="0003">Comment 3</li>
<li class="commentInList topLevelComment" data-commentid="0004">Comment 4</li>
<li class="commentInList topLevelComment" data-commentid="0005">Comment 5</li>
</ul>
How was it supposed to scrolldown to something that's faded out? Removed the fading effects and it ( scrollTop: $self.offset().top) worked like a charm.

Cant get the value of <li data-*> element. Tried Javascript as well as Jquery

The following is my dropdown list.
<ul id="navBar" data-value="">
<li data-city-value="blore">Bangalore
<ul>
<li data-city-value="delhi">Delhi</li>
<li data-city-value="che">Chennai</li>
<li data-city-value="jaipur">Jaipur</li>
<li data-city-value="hyd">Hyderabad</li>
<li data-city-value="mum">Mumbai</li>
<li data-city-value="pune">Pune</li>
</ul>
</li>
</ul>
And the following are my methods I tried to access the data-city-value attribute.
Method 1)
var cityName = document.getElementById('navBar');
var city = cityName.getAttribute('data-city-value');
alert(city);
It alerts "null"
Method 2)
var cityName = document.getElementById('navBar');
var city = cityName.dataset.cityValue;
alert(city);
It alerts "undefined".
Method 3)
$('#navBar li').click(function() {
$(this).parent().data('value', $(this).data('cityValue'));
});
alert($('#city').data('value'));
It alerts "undefined".
I checked the syntax to get data value here
It would be of great help if you can help me find where I am doing mistake.
Thanks. :)
IN your first two methods you target the top ul with id navBar. In the third method you do $(this).parent() which again takes you to the ul element.
That element does not have the data-city-value attribute.
The jquery method should be
$('#navBar').on('click','li', function(e) {
var city = $(this).data('city-value');
alert(city);
return false;
});
Demo at http://jsfiddle.net/gaby/Mb7KS/
As pointed out by Gaby, you need to reach the element firts. Try this:
$('#navBar:first-child')
This is how you can iterate through your data-city-value attributes:
$('li[data-city-value]').each(function(index,element){
alert($(element).data('city-value'));
});
You can also check my jsFiddle example.
For click events:
$(document).ready(function()
{
$('li').click(function() {
alert($(this).data('city-value'));
return false;
});
});
You should return false because the top li element has inner elements and it was triggering inner li element click event.
My second jsFiddle demo.

Jquery addClass with delay

I have a basic menu like this:
<ul>
<li>item 1</li>
<li>item2</li>
</ul>
How can I add the class "current" for each one of my <li> elements every 800 ms, and of course delete the old current element?
This'll loop forever through any number of list items:
$(document).ready(function() {
var $lis = $("li"), i = -1;
function nextCurrent() {
$lis.eq(i).removeClass("current");
$lis.eq(i=(i+1)%$lis.length).addClass("current");
setTimeout(nextCurrent, 800);
}
nextCurrent();
});
Demo: http://jsfiddle.net/nnnnnn/4skLV/
And may I suggest that before you next post a question you read this article: What have you tried?
$('li').each(function(i){
var $that = $(this);
setTimeout(function(){
$that.addClass('current').siblings().removeClass('current');
}, i *800);
});
Live DEMO

How can I call a jQuery function if the children of two different sections classes match?

So I have been trying to write jquery that make one element become active when another one is hovered. This will be used for highlighting areas on a map when a location is hovered.
I have it working for one destination using:
function engageMaps(){
var destination = $(".destination .cancun");
var pin = $(".image_map .cancun");
$(destination).hover(
function () {
$(pin).addClass("active");
},
function () {
$(pin).removeClass("active");
}
);
};
But i need it to work for all destinations based off of the elements class. If the classes match then they should be active.
I tried doing something like this (doesn't work. probably written wrong)
function engageMaps(){
var destination = (($(".destination").children()).attr('class'));
var pin = (($(".image_map").children()).attr('class'));
if($(destination) === $(pin)){
$(destination).hover(
function () {
$(pin).addClass("active");
},
function () {
$(pin).removeClass("active");
}
);
};
};
and here is the html:
<div class="image_map">
<a class="cancun" id="cancunPin" href="#">Cancun</a>
<a class="cozumel" id="cozumel" href="#">Cozumel</a>
</div>
<div class="destinations">
<ul>
<li class="destination"><a class="cancun" href="#">Cancun</a></li>
<li class="destination"><a class="Cozumel" href="#">Cozumel</a></li>
</ul>
</div>
If anyone could help me that would be awesome. I hope I explained it well enough.
This might do what you're wanting. Maybe.
http://jsfiddle.net/sUgyW/
$('.destinations a').hover(
function () {
$('.image_map a.' + $(this).attr('class')).addClass('active');
},
function () {
$('.image_map a').removeClass('active');
}
);
I also tweaked your HTML slightly: changed class="Cozumel" to class="cozumel".
That's if and only if the items have one class (like "cancun" only, not "map cancun comething else"):
function engageMaps(){
var destination = $(".destination a");
$(destination).hover(
function () {
var pin = $(".image_map ."+$(this).attr("class"));
$(pin).addClass("active");
},
function () {
var pin = $(".image_map ."+$(this).attr("class"));
$(pin).removeClass("active");
}
);
};
Otherwise, you could construct a list of all the places (classes technically), and iterate over those:
function engageMaps(cls){
var destination = $(".destination ."+cls);
var pin = $(".image_map ."+cls);
$(destination).hover(
function () {
var pin = $(".image_map ."+cls);
$(pin).addClass("active");
},
function () {
$(pin).removeClass("active");
}
);
};
var classes = ["cancun", "cozumel"];
for (var i=0; i<classes.length; i++) {
engageMaps(classes[i]);
}
something like this would work. but only if the destination classes match the image_map classes (which for some reason they don't at the moment)
$('.destinations a').hover(function(){
$('.image_map .'+$(this).attr('class')).addClass('active');
},function(){
$('.image_map .'+$(this).attr('class')).removeClass('active');
});
I'd probably change it like this:
<div class="image_map">
<a id="cancun" href="#">Cancun</a>
<a id="cozumel" href="#">Cozumel</a>
</div>
<div class="destinations">
<ul>
<li><a data-location="cancun" href="#">Cancun</a></li>
<li><a data-location="cozumel" href="#">Cozumel</a></li>
</ul>
</div>
and then use
$('.destinations a').hover(function(){
$('.image_map #'+$(this).data('location')).addClass('active');
},function(){
$('.image_map #'+$(this).data('location')).removeClass('active');
});
that way it still works if you add additional classes to the destinations

javascript prototype problem

So I have a rather basic javascript problem which I have been slamming my head into a wall over for awhile:
<div class='alist'>
<ul>
<li class='group_1'> An Item </li>
<li class='group_1'> An Item </li>
<li class='group_2'> An Item </li>
</ul>
</div>
<div class='alist'>
<ul>
<li class='group_1'> An Item </li>
<li class='group_1'> An Item </li>
<li class='group_2'> An Item </li>
</ul>
</div>
<script>
function toggle_item( num ){
$$( 'li.group_' + num ).invoke('toggle');
}
</script>
Basically, I need to create a sweeper that sets the div to display:none if all the li are display:none.
I think it would start like:
function sweep(){
$$('div.alist').each( function( s ) {
ar = s.down().children
});
}
Any suggestions for good tutorials would be welcome as well
Something like this might get you started. You'll need to iterate through the children and check if they're visible. If any of them aren't, set a flag and break from the loop. If the flag is false then you don't need to hide the div.
function sweep(){
$$('div.alist').each( function( s ) {
var shouldHide = true;
var children = s.down().childElements();
children.each(function(li) {
if(li.visible()) {
shouldHide = false;
throw $break;
}
});
if(shouldHide) {
s.hide();
}
});
}
You could use the select() method of Element to find all li descendants. And run a method Array.all for each li and check if all return true. Hide the div if all return true.
function sweep() {
// check each div
$$('div.alist').each(function(element) {
var listItems = element.select('li');
// are the list items of this div hidden?
var listItemsHidden = listItems.all(function(item) {
return item.visible();
});
// hide the div too if so
if(listIemsHidden) {
element.hide();
}
});
}
This code is untested.
This is jQuery solution (Prototype must be something similar):
$('div.alist').css('display', function () {
return $(this).find('li:visible').length < 1 ? 'none' : '';
});

Categories

Resources