Artem Saribekian
Artem Saribekian

Reputation: 356

How to add li class when clicking another div

I have two divs: #slider-next and #slider-prev. Also i have 4 li elements. On each click #slider-next i need to add .active class to each li. First look:

   <ul class="items-list">
        <li class="active" id="l1">One</li>
        <li id="l2">Two</li>
        <li id="l3">Three</li>
        <li id="l4">Four</li>
    </ul>

After click #slider-next it should looks like:

<ul class="items-list">
    <li id="l1">One</li>
    <li class="active" id="l2">Two</li>
    <li id="l3">Three</li>
    <li id="l4">Four</li>
</ul>

It should repeating by clicking like it was at start Here is my code but it adds class only for a second li:

function arrowNext() {
    if( $('#l1, #l2, #l3, #l4').hasClass('active') ) {
        $('.items-list li').removeClass('active');
        $('li:nth-child(1)').next().addClass('active');
    }
}

Upvotes: 0

Views: 180

Answers (7)

Assimilater
Assimilater

Reputation: 964

Two comments:

In general I would prefer to use $(document).ready() or something similar to ensure there is always one class="active" (since you're doing a slider seems sensible) as opposed to seeing if that condition exists.

$('li:nth-child(1)') selects the first <li> always, not the one that was previously active. What you probably want instead is

$('li.active')           // Selects the li with class active
  .removeClass('active') // returns the same li acted on
  .next()                // selects the next li
  .addClass('active');   // adds the class active

This method of "chaining" is part of what makes jQuery so convenient :)

If you want it to "wrap around" you could do something like

var $next = $('li.active')  // Selects the li with class active
  .removeClass('active')    // returns the same li acted on
  .next();                  // selects the next li
if ($next.length === 0) {
    $next = $('li:first');
}
$next.addClass('active');   // adds the class active

Upvotes: 0

Mahedi Sabuj
Mahedi Sabuj

Reputation: 2944

If You need circular Next and Previous, you can try this:

var nextCircularIndex = function(currentIndex, totalIndex) {
    currentIndex = currentIndex + 1;
    return currentIndex % totalIndex;
}

var previousCircularIndex: function (currentIndex, totalIndex) {
    currentIndex = currentIndex - 1;
    return currentIndex < 0 ? totalIndex - 1 : currentIndex;
}

Then change arrowNext like

var currentSlider = 0;
var totalSlider = 4;

function arrowNext() {
   currentSlider = nextCircularIndex(currentSlider, totalSlider);
   $("ul.items-list li.active").removeClass('active');
   $("ul.items-list li:nth-child(" + currentSlider + ")").next().addClass('active');
}

function arrowPrevious() {
   currentSlider = previousCircularIndex(currentSlider, totalSlider);
   $("ul.items-list li.active").removeClass('active');
   $("ul.items-list li:nth-child(" + currentSlider + ")").next().addClass('active');
}

Upvotes: 2

vbotio
vbotio

Reputation: 1674

I think it's a good way you to follow

$(".next").on("click", function(){


if($(".active").next("div").html() === undefined) {
    $(".active").removeClass("active");
    $("div").first().addClass("active");
  } else {
    $(".active").removeClass("active").next("div").addClass("active");
  }

})
$(".prev").on("click", function(){
    if($(".active").prev("div").html() === undefined) {
        $(".active").removeClass("active");
    $("div").last().addClass("active");
    } else {
    $(".active").removeClass("active").prev("div").addClass("active");
  }
})

here's a fiddle: https://jsfiddle.net/v58jzp9L/

here is a update with a loop :) https://jsfiddle.net/v58jzp9L/2/

Upvotes: 1

Quack
Quack

Reputation: 361

Maybe something like this:

var list_items = $(".items-list li");
var li_active = 1;
var li_total = list_items.length;

$("#prev").click(function() {
  list_items.removeClass('active');
  if (li_active == 1) {
    li_active = li_total;
  } else {
    li_active--;
  }
  $('.items-list li:nth-child(' + li_active + ')').addClass('active');
});

$("#next").click(function() {
  list_items.removeClass('active');
  if (li_active == li_total) {
    li_active = 1;
  } else {
    li_active++;
  }
  $('.items-list li:nth-child(' + li_active + ')').addClass('active');
});
.active {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="items-list">
  <li class="active" id="l1">One</li>
  <li id="l2">Two</li>
  <li id="l3">Three</li>
  <li id="l4">Four</li>
</ul>

<button id="prev">Prev</button>
<button id="next">Next</button>

Upvotes: 1

Andrew Brooke
Andrew Brooke

Reputation: 12163

I would approach it like this

function arrowNav(prev) {
  // get the current index of the active item
  var index = $('.items-list li.active').index();

  // remove the active class from all items
  $('.items-list li').removeClass('active');

  // add or subtract one if next or previous
  var newIndex = prev ? index - 1 : index + 1;

  // rolling over the top or bottom
  if (newIndex < 0)
    newIndex = $('.items-list li').length - 1;
  else if (newIndex >= $('.items-list li').length)
    newIndex = 0;

  // setting the class of the new active item
  $('.items-list li').eq(newIndex).addClass('active');
}

$('#slider-prev').on('click', function() {
  arrowNav(true)
});
$('#slider-next').on('click', function() {
  arrowNav(false)
});
.active {
  background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="items-list">
  <li class="active" id="l1">One</li>
  <li id="l2">Two</li>
  <li id="l3">Three</li>
  <li id="l4">Four</li>
</ul>
<button id="slider-prev">
  Prev
</button>
<button id="slider-next">
  Next
</button>

Upvotes: 1

wpcarro
wpcarro

Reputation: 1546

You should have some conception of state that tracks which of the lis are "active". This could be as simple as an array that looks like this:

const state = {
  list_items: [false, true, false, false]
};

Or, more succinctly, a single number, representing the index of the li that is "active"

const state = {
  active_list_item: 1
};

Then when you press next, you can increment state.active_list_item appropriately. Find a way to manage overflow. Does it wrap? If not, maybe use a createClamp(..) function. Otherwise, use a createWrap(..) function.

When the state is changed, you will want the appropriate DOM side effects to flow from the state change.

let list_items = document.getElementsByClassName('items-list')[0].children;
list_items = [].slice.apply(list_items);

list_items.forEach((list_item, i) => {
  if (i === state.active_list_item) {
    list_item.classList.add('active');
  }
  else {
    list_item.classList.remove('active');
  }
});

You should be able to figure out how to create the "previous" functionality now.

Upvotes: 0

NewDeveloper
NewDeveloper

Reputation: 301

You could use something like

var item = $("ul").closest("li");
var item2 = item.closest(".active");
item2.toggleClass("active");

if (item2.next("li") != null) {
  item2.next("li").toggleClass("active");
} else {
  item.toggleClass("active");
}

Upvotes: 0

Related Questions