Twitter Bootstrap Carousel - access current index - javascript

How do I get the current index from the carousel?
In this case I am using an unordered list. I know I could search through the list items to find the one with the 'active' CSS class, but I want to know if I can ask the carousel object directly.
Additional: being able to access the target index (on 'slide' event) would be handy also. Again, I can do this by searching with:
var idx = $('.carousel-inner li.active').index();
...and then adding/subtracting based on direction, but I am hoping for something cleaner.

Instead of adding and subtracting from the current slide, try this on the 'slide' event:
$('.carousel').on('slide',function(e){
var slideFrom = $(this).find('.active').index();
var slideTo = $(e.relatedTarget).index();
console.log(slideFrom+' => '+slideTo);
});

This worked for me (Bootstrap 3)
$("#myCarousel").on('slide.bs.carousel', function(evt) {
console.debug("slide transition started")
console.debug('current slide = ', $(this).find('.active').index())
console.debug('next slide = ', $(evt.relatedTarget).index())
})

It appears Bootstrap 4 finally has the native implementation of this.
https://github.com/twbs/bootstrap/pull/21668
$('#myCarousel').on('slide.bs.carousel', function(e){
e.direction // The direction in which the carousel is sliding (either "left" or "right").
e.relatedTarget // The DOM element that is being slid into place as the active item.
e.from // The index of the current item.
e.to // The index of the next item.
});

Nope, there is no way to access index or direction.
See here
// EDIT
Bootstrap changed repos, new link

For bootstrap 3 it's
$('#myCarousel').on('slide.bs.carousel', function (e) {
var active = $(e.target).find('.carousel-inner > .item.active');
var from = active.index();
var next = $(e.relatedTarget);
var to = next.index();
console.log(from + ' => ' + to);
})
from https://github.com/twbs/bootstrap/pull/2404#issuecomment-22362366

$(".active", e.target).index() works. Where e from:
carousel.on("slid", function (e) {
$(".active", e.target).index();
});
Found on: https://github.com/twitter/bootstrap/pull/2404#issuecomment-4589229

I'm doing it like that, that works sort of very well ;)
var slider = $("#slider-wrapper")
.carousel({
interval: 4000
})
.bind('slid', function() {
var index = $(this).find(".active").index();
$(this).find("a").removeClass('pager-active').eq(index).addClass('pager-active');
});
$("#slider-wrapper a").click(function(e){
var index = $(this).index();
slider.carousel(index);
e.preventDefault();
});

I was able to access the slide index using a jquery function from the bootstrap documentation.
$('#carousel').on('slide.bs.carousel', function(event) {
alert(event.from);
// You can use use 'event.from' in whatever way works best for you here
}
.from on the event will give you the slide where the slide instance occurs. .to will give you the slide where the slide instance is going to. Using slide.bs.carousel will execute the function before the slide animation, slid.bs.carousel will execute the function after the slide animation but the returned slide number will be the same.
There's a few other properties that the slide and slid events give you access to, I recommend checking them out on the carousel documentation page.
Note: I am using bootstrap 4.3.1.

Here's what I came up with after reading fat's comment in #Quelltextfabrik's answer.
var carousel = $("#myCarousel");
carousel.on("slid", function () {
var all = carousel.find('.item'),
active = carousel.find('.active'),
slidTo = all.index(active);
console.log("Slid - Slid To: " + slidTo);
});
carousel.on("slide", function () {
var all = carousel.find('.item'),
active = carousel.find('.active'),
slidFrom = all.index(active);
console.log("Slide - Slid From: " + slidFrom);
});

Related

jQuery prepend only to next list item after each click, not all list items at once

Simply put, my goal is to make the "next" button add a class active to the previous list item, then if the active class exists, also prepend a YES to that list item, not all list items as it is currently doing in my code.
Currently, my attempt is adding YES to all list items, I want to add YES only to the previous items after each click.
My attempt is here:
var $tabs = $('li');
$('.next').on('click', function () {
$tabs.next('li').addClass("active").css("background-color","yellow");
if ($($tabs).next().hasClass("active")){
$($tabs).prepend('YES').prev();
} else {
$($tabs).append('NO');
}
});
Code can be seen here:
http://codepen.io/anon/pen/yrjvb
I'm not sure if I understood you correctly, but this might be what you're looking for :
var $tabs = $('li');
var count = 0;
$('.next').click(function () {
var tab = $tabs.eq(count);
var link = tab.find('a[data-toggle="tab"]');
link.addClass("active").css("background-color","yellow");
if (link.hasClass("active")) {
tab.prepend('YES');
count++;
} else {
tab.append('NO');
}
});
Forked Codepen : http://codepen.io/anon/pen/pnKAc?editors=101
Basically, you were selecting all the <li> items. In my code, I select an item one-by-one.
Surely there is a better way to do it (selecting directly the next element etc., but I guess with this code you can see what's different.
Also, you say you want to add, did you mean "append", then ?
How about this approach (codepen): Store the current one, clear its active state, pick the next one ?
$('.next').on('click', function () {
var $current = $('li.active');
if(!$current.length){
$current = $('li:first');
$current.addClass('active');
}else{
$current.removeClass('active');
$current.next('li').addClass('active');
}
});

Remove an active class by clicking on a parent's brother item in JavaScript

I am working on a get a card script, that consists of 2 phases.
Selecting a card > opens a relevant window on the right
Pressing an Apply now button on that opened window > opens a relevant window on the bottom.
Right now everything works as intended, except:
I want to make so that if a person removes a card selection (.gacca1 / .gacca2), it also removes the "activated" class from the "Get card" div (.gaccaiGET), thus removing the bottom div (.gara). Right now, it keeps the "Get a card" activated, even if you deactivate the card selector.
No matter how I try (with my beginner js skills), i can't make it work.
Also, if you look at the html and css, you will see that most of the elements are positioned absolute, which is a very bad way of making this work. Unfortunately, I could not figure a way to make the positions relative, because the
.divclass.active + .otherdivclass { css }
works only for brother elements, and, even, only for the brother elements that are next to each other. Which resulted in writing poor html and css, to make it look and work the way I want it to. If you have any tips on this matter, please let me know!
Thanks
http://jsfiddle.net/4XM9A/10/
(function () {
var links = Array.prototype.slice.call(document.querySelectorAll('.gacca1'));
var links2 = Array.prototype.slice.call(document.querySelectorAll('.gacca2'));
var links3 = Array.prototype.slice.call(document.querySelectorAll('.gaccaiGET'));
var toggleClass = function (className, element) {
element.classList.toggle(className);
};
var clickHandler = function (linksToDisable) {
return function () {
toggleClass('active', this);
linksToDisable.filter(function (link) {
return link.classList.contains('active');
})
.forEach(function (link) {
toggleClass('active', link);
});
};
};
links.forEach(function (link) {
link.addEventListener('click', clickHandler(links2));
});
links2.forEach(function (link) {
link.addEventListener('click', clickHandler(links));
});
links3.forEach(function (link) {
link.addEventListener('click', function () {
toggleClass('active', this);
});
});
}());
As far as I understand you should firstly toggle '.active' of all divs of the '.gaccai' that goes after the ".active" parent. Try changing function toggleClass a bit:
var toggleClass = function (className, element) {
var array = document.querySelectorAll('.' + element.classList + ' + .gaccai .active');
for (var i = 0; i < array.length; i++) {
array[i].classList.toggle(className);
}
element.classList.toggle(className);
};

jQuery iteration though all items of a class regardless of their position in the DOM

i'm building a webpage where many span­ needs to be transitioned from one class to another to create a bg-color fadein effect. Distribution of elements of same classes is mixed through the page, but they are all grouped under common classes.
I want to create a behavior that does the following: when you click any elements of class-n, the other elements of that class transitions, with the clicked element acting as the starting point.
This is mostly figured out, thanks to some help on SO; see the jsfiddle.
$(".div").click(function () {
var itemClasses = this.classList;
var itemThread = itemClasses[1];
colorThread($(this), itemThread);
console.log(itemThread);
});
function colorThread($div, tId) {
tId = '.'+tId;
$div.toggleClass('div-clicked');
setTimeout(function () {
(function togglePrev($div) {
$div.toggleClass('div-clicked');
setTimeout(function () {
togglePrev($div.prev(tId));
}, 100);
})($div.prev(tId));
(function toggleNext($div) {
$div.toggleClass('div-clicked');
setTimeout(function () {
toggleNext($div.next(tId));
}, 100);
})($div.next(tId));
}, 100);
}
However, I am still struggling around a particular issue: I don't want the transition to stop if if encounter different class, I just want it not to toggle and keep iterating. If the jsfiddle, that would translate in all of the same color div to transition, regardless of their placement in the DOM tree.
In my togglePrev/toggleNext function, I have tried something along
if($div.hasClass(".classToTransition"))
{
$div.toggleClass(".div-clicked");
}
but couldn't get it to work properly (it doesn't ieterate to the next elements). There is something that I can't seem to grasp in the structure of that conditional. Anyone has a lead?
You really did manage to complicate something that should be pretty simple ?
$(".div").click(function () {
var coll = $('.'+this.className.replace(/(div-clicked|div)/g, '').trim()),
idx = coll.index($(this).toggleClass('div-clicked'));
$.each(coll, function(i) {
setTimeout(function() {
if (idx + i <= coll.length) coll.eq(idx + i).toggleClass('div-clicked');
if (idx - i >= 0) coll.eq(idx - i).toggleClass('div-clicked');
},i*200);
});
});
FIDDLE
It gets all the elements with the same class as the one currently clicked, and the index of the currently clicked, and then just adds and subtract 1 to the current index to get the next and previous elements. The checks are to make sure it stops when it reaches the end.
I don't want the transition to stop if if encounter different class, I just want it not to toggle and keep iterating
You might want to use nextAll(tId).first()/prevAll(tId).first() to select the next to-be-toggled element: http://jsfiddle.net/35uNW/4/. .next() does only look at the next sibling, and if that doesn't match your tId selector, no element will be selected.
If you want to iterate the different-classed elements so that you wait for each one, but don't want to toggle it, you can use your if-condition but you must remove the tId selector from the next()/prev() calls: http://jsfiddle.net/35uNW/3/.
This was a fun one. I did it a slightly different way, getting all of the matched elements and splitting them into before and after arrays.
var $allItems = $(".div");
$(".div").click(function () {
var itemClasses = this.classList;
var itemThread = itemClasses[1];
colorThread($(this), itemThread);
});
function colorThread($div, classname) {
var tId = '.'+classname,
$divs = $allItems.filter(tId),
index = $divs.index($div),
$before = $divs.slice(0, index),
before = $before.get().reverse(),
$after = $divs.slice(index+1);
$div.toggleClass('div-clicked');
$(before).each(function(i, item){
setTimeout(function () {
$(item).toggleClass('div-clicked');
}, i*100);
});
$($after).each(function(i, item){
setTimeout(function () {
$(item).toggleClass('div-clicked');
}, i*100);
});
}
Here's a working fiddle: http://jsfiddle.net/5sUr4/

Add new item to bottom of scrollabe div

I'm trying to append a div to the bottom of a another div, by clicking a button in javascript, but once the height of the outer container is reached, it no longer scrolls the list to the bottom, after an insert.
Please see the fiddle here
If you click the red add button until you get to about 13 items in the list, it seems something goes wrong with the scrollTop function, and it it no longer functions correctly (hovers around the same spot in).
I'm pretty lost on this, and have tried a bunch of different combinations of css settings for both the container and side div. Please help me.
I've reformatted your code to be more jQuery-esque. The main change, however, was to change the list.scrollTop() function so that it just scrolls to the bottom of list:
$(document).ready(function() {
var list = $("#q-d-list");
$(document).on('click', '#add', function() {
$('.active', list).removeClass("active");
var count = list.children().length + 1;
var active = $('<div />', {
'data-qid': count,
'class': 'mli active'
}).text('q' + count).appendTo(list);
list.scrollTop(list[0].scrollHeight);
});
});​
Demo: http://jsfiddle.net/MrvcB/19/
Use
list.scrollTop(list.get(0).scrollHeight);
rather than
list.scrollTop($(".active").offset().top);
Try:
$(document).ready(function () {
var count = 2;
$("#add").live("click", function () {
var list= $("#q-d-list");
// remove the active class from the old item
var $clone = $(list.find("div:last-child").removeClass("active").clone());
count+=1;
var str_count = "q"+count.toString();
$clone.addClass("active").attr("data-qid",str_count).text(str_count);
list.append($clone);
list.scrollTop(list.get(0).scrollHeight);
});
});
http://jsfiddle.net/H4Kb3/

JQuery: Using :not(.active) selector, and adding an Active class, to the item selected

I'm new to Javascript and am having a bit of an issue with using a NOT selector, and adding a class during the function, hopefully this will make sense to someone.
I am creating a small gallery, and my goal is to have clickable navigation, however the active image will redirect to another page when clicked.
Code is as follows:
$("ul#mainGallery li:not(.active) a").click(function(){
var thisListClass = $(this).parent().attr('class');
var activeListId = $(this).parent().attr('id');
var newMarginLeft = (activeListId-3) * -200;
var animateAction = {};
animateAction['margin-left'] = newMarginLeft + 'px';
$("ul#mainGallery").animate(animateAction, 1000);
$('li.active img').animate({width:'100px', height:'100px'},1000)
$(this + 'img').animate({width:'300px', height:'300px'},1000)
$(li.active).removeClass('active');
$(this).parent().addClass('active');
return false;
I know there is likely a much better way to do this, but I can't get my head around it.
Edit: I should probably say what the problem is...
When an active image is clicked, it follows the hyperlink all is well.
When a non active image is clicked, it begins the animation, then (i assume) when the 'active' class is added, instead of returning false, it returns true and follows the hyperlink.
You are binding the click event to $("ul#mainGallery li:not(.active) a") whenever that code is run (presumably on document load). The items which are not active at that point will have that item bound, and changing the class afterwards on other items won't bind this event to them. You will need to either change how you bind it or check inside the function whether the item has that class.
Something like this:
$("ul#mainGallery li a").click(function(){
if(!$(this).parent().hasClass('active')){
var thisListClass = $(this).parent().attr('class');
var activeListId = $(this).parent().attr('id');
var newMarginLeft = (activeListId-3) * -200;
var animateAction = {};
animateAction['margin-left'] = newMarginLeft + 'px';
$("ul#mainGallery").animate(animateAction, 1000);
$('li.active img').animate({width:'100px', height:'100px'},1000)
$(this + 'img').animate({width:'300px', height:'300px'},1000)
$('li.active').removeClass('active');
$(this).parent().addClass('active');
return false;
}
EDIT, or if you prefer to continue using the same selector with the :not and everything, then switch your click function to .live()
To stop the default behaviour use the preventDefault() function
$("ul#mainGallery li:not(.active) a").click(function(e){
e.preventDefault(); // will stop the default behaviour
}
Read more on Jquery docs

Categories

Resources