jQuery emptying wrong div? [duplicate] - javascript

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.

Related

Append elements with the same class to multple divs that also share a class

I'm setting up a store catalog in which I have a div with multiple list items containing 2 divs (one for picture and another one for product summary and add to cart button)
Structure would be something like this.
<div>
<ul>
<li class="product">
<div class="product-image">
<img>
</div>
<div class="product-summary">
<a class="button">Add to cart</a>
</div>
</li>
<li class="product">
<div class="product-image">
<img>
</div>
<div class="product-summary">
<a class="button">Add to cart</a>
</div>
</li>
<ul>
</div>
I want to move the Add To Cart button to the div that contains the image.
I tried with this jQuery
jQuery(document).ready(function(){
jQuery(".product-image").append(jQuery('.button'));
});
But this adds every sigle button to the image div, and I end up with 10+ add to cart buttons on every product. Is there any way to only move the button within each li element to its respective image div?
Use a .each() loop and then move the button with the same index.
let buttons = $(".button");
$(".product-image").each(function(i) {
$(this).append(buttons.eq(i));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<ul>
<li class="product">
<div class="product-image">
<img>Product 1
</div>
<div class="product-summary">
<a class="button">Add to cart</a>
</div>
</li>
<li class="product">
<div class="product-image">
<img>Product 2
</div>
<div class="product-summary">
<a class="button">Add to cart</a>
</div>
</li>
<ul>
</div>

How to make an active view type with classlist add and remove?

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

jQuery get attibutes and values from all elements inside a class

I'm scraping a website where it has the following HTML structure
<div id="list" class="book-list">
<div id="stream_1" class="stream collapsed">
<h3 id="s-1" rel="1"><div><a name="st_1" class="st st_1">Version 1</a></div></h3>
<div class="volume last">
<h4 id="v-1-1">Volume 1<span class="range">Chapter 1</span></h4>
<ul class="chapter">
<li id="b-922893" class="new">
<span>
<a class="ch sts sts_1" target="_blank" href="link/1">vol.1 ch.1</a>
</span>
<i>Yesterday 08:27 am</i>
<em>
1
3
6
10
all
of 44 </em>
</li>
</ul>
</div>
</div>
<div id="stream_5" class="stream">
<h3 id="s-5" rel="5"><div><a name="st_5" class="st st_5">Version 2</a></div></h3>
<div class="volume last">
<h4 id="v-5-">Volume <i>[Null]</i><span class="range">Chapter 1</span></h4>
<ul class="chapter">
<li id="b-922873" class="new">
<span>
<a class="ch sts sts_5" target="_blank" href="links5/c1/1">ch.1</a>
</span>
<i>Yesterday 08:10 am</i>
<em>
1
3
6
10
all
of 44 </em>
</li>
</ul>
</div>
</div>
</div>
I want to use jQuery to get the links from the divs to get something like this
{
"vol.1 ch.1" : "link/1",
"ch.2" : "link/2"
}
As all the items i want has the class ch sts i wanted to get them with the selector, and trying to use each() but didn't work as it shows nodes...
Here's what how i'm trying:
$d('.ch').map(function(){
console.log('This: href',$(this).attr("href"));
}).get();
It is simpler than you thought. Since you've mentioned that you only want to parse links with ch sts classes, I changed the selector.
var map = {};
$(".ch.sts").each(function() {
map[$(this).text()] = $(this).attr("href");
});
console.log(map);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="list" class="book-list">
<div id="stream_1" class="stream collapsed">
<h3 id="s-1" rel="1"><div><a name="st_1" class="st st_1">Version 1</a></div></h3>
<div class="volume last">
<h4 id="v-1-1">Volume 1<span class="range">Chapter 1</span></h4>
<ul class="chapter">
<li id="b-922893" class="new">
<span>
<a class="ch sts sts_1" target="_blank" href="link/1">vol.1 ch.1</a>
</span>
<i>Yesterday 08:27 am</i>
<em>
1
3
6
10
all
of 44 </em>
</li>
</ul>
</div>
</div>
<div id="stream_5" class="stream">
<h3 id="s-5" rel="5"><div><a name="st_5" class="st st_5">Version 2</a></div></h3>
<div class="volume last">
<h4 id="v-5-">Volume <i>[Null]</i><span class="range">Chapter 1</span></h4>
<ul class="chapter">
<li id="b-922873" class="new">
<span>
<a class="ch sts sts_5" target="_blank" href="links5/c1/1">ch.1</a>
</span>
<i>Yesterday 08:10 am</i>
<em>
1
3
6
10
all
of 44 </em>
</li>
</ul>
</div>
</div>
</div>
Get all the Elements with class name.
Get the text value and "href" attribute.
x = document.getElementsByClassName("ch sts");
for(i =0; i<x.length; i++) {
console.log(x[i].text +" "+ x[i].getAttribute("href"));
}

Hiding and showing fields via Javascript based on the type of the category the results item has

I have a dynamic list of properties on a search results page, the problem I am having on each individual search result is that if it is a certain property type i.e. Land it does not need the bedrooms and bathrooms fields within that search result to show, but if it is a Villa, the fields would show.
I would need to show and hide fields on the page load in JS like my example above on each individual search result as if I do a general JS function for Land hiding the div classes for bedrooms and bathrooms, there could also be a Villa on the page needing those fields.
If anyone could help with some JS to help me solve this issue above, it would be much appreciated!
Heres some of the Html Results below, you will see there are multiple property types, so different fields should be show/hidden
<div class="property-listing">
<ul>
<li class="col-md-12">
<div class="col-md-4">
<a href="/propertydetails.aspx?SalePropertyID=615237" class="property-featured-image"><div class="overlay" style="line-height:167px"><i class="fa fa-search"></i></div>
<img src="http://example.com/ImageProcessor.aspx?watermarkImageFileName=&Text=NEW LISTING&imageURL=487/Sales/615237/615237_7969.jpg" alt="Villa in Javea">
<span class="images-count">
<i class="fa fa-link"></i>
MidasS
</span>
</a>
</div>
<div class="col-md-8">
<div class="property-info">
<div class="price"><span>115.000</span><strong>€</strong></div>
<div class="title">
<a href="/propertydetails.aspx?SalePropertyID=615237" title="Villa in Javea">
Villa in Javea
</a>
</div>
<span class="location"><i class="fa fa-map-marker"></i> Alicante, SPAIN</span>
<p>A beautiful and rustic style 'home' offering spectacular views over the coast, the mountains and the Mediterranean Sea.</p>
</div>
<div class="property-amenities clearfix">
<span id="spbeds"><strong>2</strong>Bedrooms</span>
<span id="spbaths"><strong>1</strong>Bathrooms</span>
<span id="sppool"><strong>Yes</strong>Pool</span>
</div>
</div>
</li>
<li class="col-md-12">
<div class="col-md-4">
<a href="/propertydetails.aspx?SalePropertyID=638700" class="property-featured-image"><div class="overlay" style="line-height:167px"><i class="fa fa-search"></i></div>
<img src="http://example.com/ImageProcessor.aspx?watermarkImageFileName=&Text=REDUCED&imageURL=487/Sales/638700/638700_1145.jpg" alt="Apartment in Famagusta">
<span class="images-count">
<i class="fa fa-link"></i>
PRO1011
</span>
</a>
</div>
<div class="col-md-8">
<div class="property-info">
<div class="price"><span>155.000</span><strong>€</strong></div>
<div class="title">
<a href="/propertydetails.aspx?SalePropertyID=638700" title="Apartment in Famagusta">
Apartment in Famagusta
</a>
</div>
<span class="location"><i class="fa fa-map-marker"></i> Famagusta, CYPRUS</span>
<p>hnglkrehnblarjl;kbkhmtr;mnb;rstlmnstrn</p>
</div>
<div class="property-amenities clearfix">
<span id="spbeds"><strong>0</strong>Bedrooms</span>
<span id="spbaths"><strong>0</strong>Bathrooms</span>
<span id="sppool"><strong>No</strong>Pool</span>
</div>
</div>
</li>
<li class="col-md-12">
<div class="col-md-4">
<a href="/propertydetails.aspx?SalePropertyID=636364" class="property-featured-image"><div class="overlay" style="line-height:188px"><i class="fa fa-search"></i></div>
<img src="http://example.com/487/Sales/636364/636364_5562.jpg" alt="Country House in Not Specified">
<span class="images-count">
<i class="fa fa-link"></i>
cyc130
</span>
</a>
</div>
<div class="col-md-8">
<div class="property-info">
<div class="price"><span>175.000</span><strong>€</strong></div>
<div class="title">
<a href="/propertydetails.aspx?SalePropertyID=636364" title="Country House in Not Specified">
Country House in Not Specified
</a>
</div>
<span class="location"><i class="fa fa-map-marker"></i> Andalucia, SPAIN</span>
<p>;.lkijuhygtfrdeswaq</p>
</div>
<div class="property-amenities clearfix">
<span id="spbeds"><strong>3</strong>Bedrooms</span>
<span id="spbaths"><strong>1</strong>Bathrooms</span>
<span id="sppool"><strong>Yes</strong>Pool</span>
</div>
</div>
</li>
<br> <br>
<div class="pagination">
<span class="disabled"><i class="fa fa-chevron-left"></i></span>
1
2
3
4
<i class="fa fa-chevron-right"></i>
</div>
</ul>
</div>
I'm just gonna go ahead and make up my own HTML structure to demonstrate the simple if/else statement you would make with jQuery.
function hideFields() {
$(".result").each( function() {
if ( $(this).hasClass("land") ) {
$(this).children(".bedroom").hide();
$(this).children(".bathroom").hide();
}
else if ( $(this).hasClass("villa") ) {
$(this).children(".land-area").hide();
}
});
}
hideFields();
span {
display:block;
border:1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<div class="result villa"><b>Villa</b><br>
<span class="bedroom">Bedroom</span>
<span class="bathroom">Bathroom</span>
<span class="location">Location</span>
<span class="land-area">Land-area</span>
</div>
<br>
<div class="result land"><b>Land</b><br>
<span class="bedroom">Bedroom</span>
<span class="bathroom">Bathroom</span>
<span class="location">Location</span>
<span class="land-area">Land-area</span>
</div>
Your HTML seems confusing for multiple reasons, which you can easily fix to use this method:
1) sppools, spbaths, spbeds should indeed be classes rather than IDs. This is due to IDs being unique identifiers - they should hence not appear more than once on each page, whereas classes identify a "type" (class) of item, which may appear multiple times. Multiple instances of the same ID will mess with your CSS and JS.
2) There is no clear definition within each result of what type of result this is (or I can't seem to find it, at least?).
Words like "villa" or "house" indeed appear in the title-tag, but having to search within these is an inefficient way of performing the action.
Instead, make your code show the type of content as a class on each li-item or the initial div-item.

jQuery set element li data from array

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.

Categories

Resources