This should be an easy fix but I just can't wrap my head around javascript selectors just yet. I have a list of h3 li elements that each contain content that is shown on click. I want a toggle arrow to change from up to down on click. But with the JS code below this happens for all li elements including the one for which the collapsed content is not showing. How can I fix this?
$(document).ready(function () {
$('#toggle-view li').click(function () {
var text = $(this).children('div.panel');
if (text.is(':hidden')) {
text.slideDown('200');
$("h3 .fa-caret-up").removeClass("fa-caret-up").addClass("fa-caret-down");
} else {
text.slideUp('200');
$("h3 .fa-caret-down").removeClass("fa-caret-down").addClass("fa-caret-up");
}
});
});
Here is the html in case you need it:
<ul class="services-ul facebook-ul" id="toggle-view">
<li>
<h3><i class="fa fa-check"></i>Header 1<i class="fa fa-caret-up"></i></h3>
<span>+</span>
<div class="panel">
<p>dummy text...</p>
</div>
</li>
<li>
<h3><i class="fa fa-check"></i>Header 2<i class="fa fa-caret-up"></i></h3>
<span>+</span>
<div class="panel">
<p>dummy text...</p>
</div>
</li>
<li>
<h3><i class="fa fa-check"></i>Header 3<i class="fa fa-caret-up"></i></h3>
<span>+</span>
<div class="panel">
<p>dummy text...</p>
</div>
</li>
<li>
<h3><i class="fa fa-check"></i>Header 4<i class="fa fa-caret-up"></i></h3>
<span>+</span>
<div class="panel">
<p>dummy text...</p>
</div>
</li>
</ul>
You need to specify the elements relative to this (which within your click event is the li element which has been clicked on).
Simply wrap this in a jQuery selector ($(this)), then use jQuery's find() method to find the elements contained within it:
$(this).find('.fa-caret-up').removeClass('.fa-caret-up').addClass('.fa-caret-down');
And:
$(this).find('.fa-caret-down').removeClass('fa-caret-down').addClass('fa-caret-up');
Related
I thought this would work outright, but I must be missing something.
I have a nested span of content in a div and I'm trying to get that span to show on hover (and hide on mouseout).
I thought that just doing a $(this).find('.name-of-span') inside of ahover` function would do it, but something must be missing.
This is what I have:
HTML:
<div class="parent-item">
<h3>title 01</h3>
<span class="meta--reveal">
<a class="btn" href="#">Link</a>
</span>
</div>
<div class="parent-item">
<h3>title 02</h3>
<span class="meta--reveal">
<a class="btn" href="#">Link</a>
</span>
</div>
JS:
$('.parent-item').hover(function() {
$(this).find('.meta--reveal').show();
});
I thought that should work, but again, I'm probably missing something.
I also tried to do this with CSS with an adjacent sibling selector, but that wasn't working either.
You can construct a CSS rule that only hides the nested element if the parent is not hovered.
.parent-item:not(:hover) .meta--reveal {
display: none;
}
<div class="parent-item">
<h3>title 01</h3>
<span class="meta--reveal">
<a class="btn" href="#">Link</a>
</span>
</div>
<div class="parent-item">
<h3>title 02</h3>
<span class="meta--reveal">
<a class="btn" href="#">Link</a>
</span>
</div>
Otherwise, your existing logic does work. You're just missing the second method that reverts the show.
$('.parent-item').hover(function() {
$(this).find('.meta--reveal').show();
}, function(){
$(this).find('.meta--reveal').hide();
});
.parent-item .meta--reveal {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent-item">
<h3>title 01</h3>
<span class="meta--reveal">
<a class="btn" href="#">Link</a>
</span>
</div>
<div class="parent-item">
<h3>title 02</h3>
<span class="meta--reveal">
<a class="btn" href="#">Link</a>
</span>
</div>
this is working. First, the going to show element must be 'display: none'.
$('.parent-item').hover(function() {
$(this).find('.meta--reveal').show();
});
.meta--reveal {
display:none;
}
<div class="parent-item">
<h3>title 01</h3>
<span class="meta--reveal">
<a class="btn" href="#">Link</a>
</span>
</div>
<div class="parent-item">
<h3>title 02</h3>
<span class="meta--reveal">
<a class="btn" href="#">Link</a>
</span>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
Also usable children() instead of find()
Hide all the link before displaying the selected one.
$('.parent-item').hover(function() {
//hide all the link before displaying the selected one.
$('.meta--reveal').hide();
//displays the selected item
$(this).find('.meta--reveal').show();
});
Use jQuery to add and remove classes to toggle display, teamed up with the '.children' for targeted selection
$(document).ready(function() {
$(".hover").mouseover(function() {
$(this).children('.target').removeClass("hide").addClass("reveal");
});
$(".hover").mouseleave(function() {
$(this).children('.target').removeClass("reveal").addClass("hide");
});
});
.hide {
display: none;
}
.reveal {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="hover">
<h3>title 01</h3>
<div class="target hide">
<span class="metaReveal"><a class="btn" href="#">Link</a></span>
</div>
</div>
<div class="hover">
<h3>title 02</h3>
<div class="target hide">
<span class="metaReveal"><a class="btn" href="#">Link</a></span>
</div>
</div>
Ok so I have game list, which is currently styled in a thumbnail kind of view. I have made 3 other classes which when added change the child elements of the list elements to make a list view. I have one which changes the li's themselves, 2 which change the child nodes of that li.
I have two buttons which should control the users preferred view type. They have an active class which stays on to show it is the active view.
So here's the question, how do i select the li's, and there child elements, to replace the view. So when clicked, the list button will add those classes. I will also need the thumbnail view button to remove those classes but i can figure that afterwards.
The markup:
<div id="View">
<button id="boxes" class="btn active" title="Thumnbnail View" onclick="thumbview()">
<i class="fas fa-th"></i>
</button>
<button id="lines" class="btn" title="List View" onclick="listview()">
<i class="fas fa-list-ul"></i>
</button>
</div>
<div id="sortcontainer">
<li class="game" id="75">
<a href="Radiant_Defence.html">
<img src="Games_images/radiantdefence/banner_image.png">
<h2 class="title">Radiant Defence</h2>
<h2 class="date" id="2012">(2012)</h2>
<h3>75/100</h3>
</a>
</li>
<li class="game" id="80">
<a href="plantsvszombies2.html">
<img src="Games_images/Plantsvszombies2/bannerimage.jpg">
<h2 class="title">Plants vs Zombies 2</h2>
<h2 class="date" id="2013">(2013)</h2>
<h3>80/100</h3>
</a>
</li>
<li class="game" id="45">
<a href="link">
<img src="games_category_placeholder.jpg">
<h2 class="title">Some game</h2>
<h2 class="date" id="2017">(2017)</h2>
<h3>45/100</h3>
</a>
</li>
<li class="game" id="80">
<a href="link">
<img src="games_category_placeholder.jpg">
<h2 class="title">Fieldrunners 2</h2>
<h2 class="date" id="2016">(2016)</h2>
<h3>80/100</h3>
</a>
</li>
</div>
And the JavaScript I have so far (still new)
function listview() {
var container = document.getElementById("sortcontainer");
var li = container.getElementsByTagName("li");
for (var i = 0; i < li.length; i++);
li.classList.add("lilistview");
};
Thankyou in advance if anyone has any suggestions
$(".sidebar>i:nth-child(3)").on("click", showMenu);
<div class="sidebar">
<i class="fa fa-volume-up"></i>
<div class="colorPalette">
<button class="submit">Submit</button>
<p>Color Pallette:</p><br />
<div class="colors_1">
<span id="color1"></span>
<span id="color2"></span>
<span id="color3"></span>
</div>
<div class="colors_2">
<span id="color4"></span>
<span id="color5"></span>
<span id="color6"></span>
</div>
</div>
<i class="fa fa-arrow-circle-o-left" title="Back to Menu"></i>
</div>
I need to select the 2nd (Back to Menu) button. So why nth-child(3) works but not nth-child(2)?
Since :nth-child(n) selects all children inside a parent element, regardless of what they are. So, in your case:
.sidebar>i:nth-child(3)
// This is the 3rd child, i tag
.sidebar>i:nth-child(2)
// This is the 2nd child, div tag
console.log($('.sidebar>i:nth-child(1)')[0])
console.log($('.sidebar>:nth-child(2)')[0])
console.log($('.sidebar>i:nth-child(2)')[0])
console.log($('.sidebar>i:nth-child(3)')[0])
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidebar">
<i class="fa fa-volume-up"></i>
<div class="colorPalette">Test</div>
<i class="fa fa-arrow" title="Back to Menu"></i>
</div>
What you need is actually :nth-of-type() selector.
console.log($('.sidebar>i:nth-of-type(1)')[0])
console.log($('.sidebar>i:nth-of-type(2)')[0])
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidebar">
<i class="fa fa-volume-up"></i>
<div class="colorPalette">
Test
</div>
<i class="fa fa-arrow" title="Back to Menu"></i>
</div>
From JQuery's docs:
The :nth-child(n) pseudo-class is easily confused with :eq(n), even though the two can result in dramatically different matched elements. With :nth-child(n), all children are counted, regardless of what they are, and the specified element is selected only if it matches the selector attached to the pseudo-class. With :eq(n) only the selector attached to the pseudo-class is counted, not limited to children of any other element, and the (n+1)th one (n is 0-based) is selected.
This question already has answers here:
How to append one jQuery element already in the DOM to another element?
(5 answers)
Closed 3 months ago.
I've been working on a filter plugin using HTML5's data-* attribute, but jQuery (or something) keeps emptying the wrong div.
Basically I have two divs with different classes. '.gallery-source' is the class of the div with ALL of the content (and the 'display' property is set to 'none' value, so it doesn't show up in the document); while '.gallery' on the first hand is empty but then given the contents of '.gallery-source'.
Once the user has selected options to filter in the dropdowns (an unordered list of items, with links that have data-* values matching some of the contents of '.gallery-source' data-* values), the '.gallery' div is emptied and then each matching content (same data-* values as set in the dropdowns) of '.gallery-source' is appended inside '.gallery'.
The code looks something like this:
// Append everything from .gallery-source to .gallery in order to show ALL work (filters may be applied later)
var gallerySource = $('.works-content .gallery-source').html();
$('.works-content .gallery').html(gallerySource);
// Attribute filtering for all work inside .gallery
$('ul#artist-dropdown li a, ul#technique-dropdown li a, ul#material-dropdown li a').on('click', function() {
// Get selected filter on form
var artistFilterValue = $('.works-content .filter-dropdowns .dropdown-wrapper a.button.artist > span').attr('data-filter-artist');
var techniqueFilterValue = $('.works-content .filter-dropdowns .dropdown-wrapper a.button.technique > span').attr('data-filter-technique');
var materialFilterValue = $('.works-content .filter-dropdowns .dropdown-wrapper a.button.material > span').attr('data-filter-material');
// Empty .gallery in order to fill it later with filtered work
$('.works-content .gallery').empty();
// Get filtered elements and append them to .gallery
$('.single-work[data-artist~="' + artistFilterValue + '"][data-technique~="' + techniqueFilterValue + '"][data-material~="' + materialFilterValue + '"]').each(function(){
$('.works-content .gallery').append($(this));
});
});
The document initially looks like this (both '.gallery' and '.gallery-source' are populated):
<div class="row works-content">
<div class="row">
<div class="small-12 medium-12 large-12 columns filter-dropdowns">
<div class="dropdown-wrapper">
Filtrar por:
<span class="dropdown-label">Artista</span>
<span data-filter-artist="all">Seleccionar</span> <i class="fa fa-chevron-down"></i><br>
<ul id="artist-dropdown" data-dropdown-content="" class="f-dropdown">
<li><span data-filter-artist="all">Todos</span></li>
<li><span data-filter-artist="name-one">Name One</span></li>
<li><span data-filter-artist="name-two">Name Two</span></li>
</ul>
</div>
<div class="dropdown-wrapper">
Técnica:
<span data-filter-technique="all">Seleccionar</span> <i class="fa fa-chevron-down"></i><br>
<ul id="technique-dropdown" data-dropdown-content="" class="f-dropdown">
<li><span data-filter-technique="all">Todos</span></li>
<li><span data-filter-technique="acrylic">Acrílico</span></li>
<li><span data-filter-technique="mixed-paper">Mixta sobre papel</span></li>
<li><span data-filter-technique="mixed-fabric">Mixta sobre tela</span></li>
<li><span data-filter-technique="oil">Óleo</span></li>
</ul>
</div>
<div class="dropdown-wrapper">
Soporte:
<span data-filter-material="all">Seleccionar</span> <i class="fa fa-chevron-down"></i><br>
<ul id="material-dropdown" data-dropdown-content="" class="f-dropdown">
<li><span data-filter-material="all">Todos</span></li>
<li><span data-filter-material="fabric">Tela</span></li>
<li><span data-filter-material="paper">Papel</span></li>
</ul>
</div>
<ul class="button-group filter-buttons">
<li class="active show-all">Todas</li>
<li class="show-available">Disponibles</li>
<li class="show-sold">Vendidas</li>
</ul>
</div>
</div>
<div class="row gallery-source">
<div data-artist="name-one all" data-technique="oil all" data-material="paper all" class="small-12 medium-4 large-4 columns single-work available-work">
<a class="work-lightbox" href="img/work/name-one/3.jpg">
<div class="work-image-wrapper">
<div class="work-image" style="background-image: url(img/work/name-one/3.jpg);"></div>
</div>
<img class="avatar" src="img/artists/name-one.png">
</a>
<a href="" class="artist-name">
<h2>Name One <i class="fa fa-plus-circle"></i></h2>
</a>
<ul class="details">
<li class="title">"Título de obra"</li>
<li>Código SUA1005</li>
<li>Tamaño: 140 x 180 cm.</li>
<li>Soporte: Papel</li>
<li>Técnica: Óleo</li>
</ul>
</div>
<div data-artist="name-two all" data-technique="acrylic all" data-material="fabric all" class="small-12 medium-4 large-4 columns end single-work sold-work">
<a class="work-lightbox" href="img/work/name-two/5.jpg">
<img class="sold" src="img/work/sold.png">
<div class="work-image-wrapper">
<div class="work-image" style="background-image: url(img/work/name-two/5.jpg);"></div>
</div>
<img class="avatar" src="img/artists/name-two.png">
</a>
<a href="" class="artist-name">
<h2>Name Two <i class="fa fa-plus-circle"></i></h2>
</a>
<ul class="details">
<li class="title">"Título de obra"</li>
<li>Código SUA1005</li>
<li>Tamaño: 140 x 180 cm.</li>
<li>Soporte: Tela</li>
<li>Técnica: Acrílico</li>
</ul>
</div>
</div>
<div class="row gallery">
<div data-artist="name-one all" data-technique="oil all" data-material="paper all" class="small-12 medium-4 large-4 columns single-work available-work">
<a class="work-lightbox" href="img/work/name-one/3.jpg">
<div class="work-image-wrapper">
<div class="work-image" style="background-image: url(img/work/name-one/3.jpg);"></div>
</div>
<img class="avatar" src="img/artists/name-one.png">
</a>
<a href="" class="artist-name">
<h2>Name One <i class="fa fa-plus-circle"></i></h2>
</a>
<ul class="details">
<li class="title">"Título de Obra"</li>
<li>Código ejemplo</li>
<li>Tamaño: 140 x 180 cm.</li>
<li>Soporte: Papel</li>
<li>Técnica: Óleo</li>
</ul>
</div>
<div data-artist="name-two all" data-technique="acrylic all" data-material="fabric all" class="small-12 medium-4 large-4 columns end single-work sold-work">
<a class="work-lightbox" href="img/work/name-two/5.jpg">
<img class="sold" src="img/work/sold.png">
<div class="work-image-wrapper">
<div class="work-image" style="background-image: url(img/work/name-two/5.jpg);"></div>
</div>
<img class="avatar" src="img/artists/name-two.png">
</a>
<a href="" class="artist-name">
<h2>Name Two <i class="fa fa-plus-circle"></i></h2>
</a>
<ul class="details">
<li class="title">"Título de obra"</li>
<li>Código ejempl5</li>
<li>Tamaño: 140 x 180 cm.</li>
<li>Soporte: Tela</li>
<li>Técnica: Acrílico</li>
</ul>
</div>
</div>
</div>
But after selecting an option in one of the filter dropdowns, '.gallery-source' is empty :(
What am I missing here? I think I'm going crazy!
Anyway, any help will be much appreciated.
.append moves the entire node from .gallery-source to .gallery. You want to do this instead:
$(this).clone().appendTo('.works-content .gallery');
You can read about .clone() here.
Here's a jsFiddle demo.
The API docs of empty also say:
... If we had any number of nested elements inside <div class="hello">, they would be removed, too.
So your $('.works-content .gallery').empty() may remove more than you want it to.
If I have a list:
<div class="item active ui-sortable">
<li class="player ui-droppable" data-name="Kev" data-pick-id="534dd2424b65762a89020000">
Teddy Bridgewater
<div class="pull-right" id="player-badges">
<span id="points-holder">
10
</span>
<span class="remove-player player-badge">
<i class="fa fa-trash-o"></i>
</span>
</div>
</li>
<li class="player pick-blank ui-droppable" data-name="" data-pick-id="534dd2424b65762a89030000">
EMPTY
<div class="pull-right" id="player-badges">
<span id="points-holder">
7
</span>
</div>
</li>
<li class="player ui-droppable" data-name="kevin" data-pick-id="534dd2424b65762a89040000">
kevin
<div class="pull-right" id="player-badges">
<span id="points-holder">
5
</span>
<span class="remove-player player-badge">
<i class="fa fa-trash-o"></i>
</span>
</div>
</li>
</div>
And I'm making an array of data-pick-id, how would I then rewrite this list based on the array ["534dd2424b65762a89020000", "534dd2424b65762a89030000", "534dd2424b65762a89040000"]?
Context: I'm using jquery-sortable and want to preserve the dom structure of the data-pick-id only. That way I can change all the contents and update to server while retaining the actual dom position by ID.
Again, all I want to do is loop through and write that array to each data-pick-id. Would a loop be the best option?
A simple .each() would suffice:
var ids = [1, 2, 3];
$('.player').each(function(i) {
$(this).data('pick-id', ids[i]);
});
You may wish to make the selector more explicit.