J'ai du mal à afficher un élément au dernier élément d'une liste. Fondamentalement, j'ai une liste qui masque et affiche un bouton en recherchant une classe .
Mon problème est quand il recherche le dernier li dans
XXX
Code JS:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="multi-single-next" class="button">Single next</button>
<button id="multi-next-multi-item" class="button">Multi item</button>
<ul class="pagnation">
<li class="single-data-item"><div class="data-item">1</div></li>
<li class="single-data-item"><div class="data-item">2</div></li>
<li class="single-data-item has-multi-items">
<ul class="pagnation-2">
<li>3a</li>
<li>3b</li>
<li>3c</li>
</ul>
</li>
<li class="single-data-item"><div class="data-item">4</div></li>
<li class="single-data-item"><div class="data-item">5</div></li>
</ul>Le problème est d'essayer de trouver le dernier li et de masquer / afficher les boutons. Il ajoute un autre élément à la liste, puis masque / affiche les boutons. Vous pouvez le voir ci-dessous après 3C et une autre puce est ajoutée, puis reprend la normale.
.single-data-item { display: none; }
ul.pagnation-2 li { display: none; }
#multi-next-multi-item { display: none; }
$('#multi-single-next').click(function() {
let $item;
if(!$('ul.pagnation li.single-data-item.active').length) {
$item = $('ul.pagnation li.single-data-item').first();
}
else {
$prev = $('ul.pagnation li.single-data-item.active');
$item = $prev.next();
if(!$prev.next().length) {
$prev.removeClass('active');
$prev.hide();
return;
}
$prev.removeClass('active');
$prev.hide();
}
$item.addClass('active');
$item.show();
// sub items
$('ul.pagnation-2 li').removeClass('active');
if($item.hasClass('has-multi-items')) {
const $sub = $item.find('ul li').first();
$sub.addClass('active');
$sub.show();
$('#multi-next-multi-item').css('display','block');
$('#multi-single-next').css('display','none');
}
});
$('#multi-next-multi-item').click(function() {
const $item = $('ul.pagnation-2 li.active');
const $next = $item.next();
$item.removeClass('active');
$item.hide();
$next.addClass('active');
$next.show();
if($item.is(':last-child')) {
$('#multi-next-multi-item').css('display', 'none');
$('#multi-single-next').css('display', 'block');
}
});
if($item.is(':last-child')) {
$('#multi-next-multi-item').css('display', 'none');
$('#multi-single-next').css('display', 'block');
}
3 Réponses :
<ul class="pagnation">
<li class="single-data-item"><div class="data-item">1</div></li>
<li class="single-data-item"><div class="data-item">2</div></li>
<li class="single-data-item has-multi-items"><ul class="pagnation-2">
<li>3a</li>
<li>3b</li>
<li>3c</li>
**</ul></li>**
<li class="single-data-item"><div class="data-item">4</div></li>
<li class="single-data-item"><div class="data-item">5</div></li>
</ul>
Are you dynamically adding the HTML? if not did you try to delete that extra line on your code?
Vous semblez mal interpréter le code HTML. Ce n'est pas une ligne supplémentaire. Notez l'ouverture qui n'est pas en retrait
Une approche légèrement différente utilisant des tableaux . Vous pouvez itérer et définir les éléments dans un tableau, puis conserver un index de l'élément visible actuel. Cela laisse derrière lui le mal de tête d'analyser l'arbre lors de l'événement click .
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="multi-single-next" class="button">Single next</button>
<button id="multi-next-multi-item" class="button">Multi item</button>
<ul class="pagnation">
<li class="single-data-item">
<div class="data-item">1</div>
</li>
<li class="single-data-item">
<div class="data-item">2</div>
</li>
<li class="single-data-item has-multi-items">
<ul class="pagnation-2">
<li>3a</li>
<li>3b</li>
<li>3c</li>
</ul>
</li>
<li class="single-data-item">
<div class="data-item">4</div>
</li>
<li class="single-data-item">
<div class="data-item">5</div>
</li>
</ul>
.single-data-item {
display: none;
}
ul.pagnation-2 li {
display: none;
}
#multi-next-multi-item {
display: none
}
var items = [];
var currentIndex = 0;
var currentItem;
$(document).ready(function() {
$('.single-data-item').each((i, e) => {
if ($(e).hasClass('has-multi-items')) {
[...$(e).find('li')].forEach(i => items.push($(i)))
} else {
items.push($($(e).find('div')));
}
})
});
$('#multi-single-next, #multi-next-multi-item').click(function() {
if (currentItem) {
hideItem(currentItem)
}
currentItem = items[currentIndex % items.length];
showItem(currentItem);
currentIndex++;
});
function showItem(item) {
if (item.is('div')) {
item.parent().show();
$('#multi-single-next').show();
$('#multi-next-multi-item').hide();
} else {
item.show();
item.closest('.single-data-item').show();
$('#multi-single-next').hide();
$('#multi-next-multi-item').show();
}
}
function hideItem(item) {
if (item.is('div')) {
item.parent().hide();
} else {
item.hide();
item.closest('.single-data-item').hide();
}
}
ça ne marche pas. Le bouton "multi" n'apparaît jamais. Le bouton dans votre exemple dit toujours "Single next" .... Essayez de regarder à nouveau l'exemple OP.
Voici une logique plus simple basée sur une collection de tous les qui ne sont pas ceux avec la classe multi-items .
Le suivant l'élément est déterminé par l'index de l'élément actif dans cette collection.
Un gestionnaire de clic unique peut être utilisé pour les deux boutons
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="multi-single-next" class="button">Single next</button>
<button id="multi-next-multi-item" class="button">Multi item</button>
<ul class="pagnation">
<li class="single-data-item">
<div class="data-item">1</div>
</li>
<li class="single-data-item">
<div class="data-item">2</div>
</li>
<li class="single-data-item has-multi-items">
<ul class="pagnation-2">
<li>3a</li>
<li>3b</li>
<li>3c</li>
</ul>
</li>
<li class="single-data-item">
<div class="data-item">4</div>
</li>
<li class="single-data-item">
<div class="data-item">5</div>
</li>
</ul>
.single-data-item {
display: none;
}
ul.pagnation-2 li {
display: none;
}
#multi-next-multi-item {
display: none
}
const $li = $('.pagnation li').not('.has-multi-items'),
$multi = $('.has-multi-items');
const $buttons = $('#multi-single-next, #multi-next-multi-item').click(function() {
let $item;
//easiest to always hide multi then use `add()` below to show the parent as needed
$multi.hide();
if (!$li.filter('.active').length) {
$item = $li.first();
} else {
const $prev = $li.filter('.active').removeClass('active').hide(),
nextIdx = $li.index($prev) + 1;
$item = nextIdx < $li.length ? $li.eq(nextIdx) : $li.first();
}
const $multiParent = $item.closest('.has-multi-items')
// toggle the buttons based on parent being multi or not
const isMulti = $multiParent.length > 0;
$buttons.first().toggle(!isMulti)
$buttons.last().toggle(isMulti)
// use add() to include the parent multi (if it exists) to show both
$item.addClass('active').add($multiParent).show();
});
dans votre événement de clic multi-boutons, remplacez $ item par $ next sur votre dernière condition. Cela résout le problème, mais cette logique n'est pas géniale. Il existe de meilleures solutions ci-dessous. if ($ item.is (': last-child')) devrait être if ($ next.is (': last-child'))