jQuery - Deleting 'corresponding' items - javascript

I have a list with two different kinds of items, product-x and product-y.
When the user deletes product-x I need it's equivalent product-y to also delete and vise-versa.
I've tried this a couple of different ways but nothing seems to be working. I appreciate any help!
JS
$(document).on('click', '.delete-item', function(e) {
$(this).parents('.product-x').delay(500).remove();
$(this).parents('.product-y').delay(500).remove();
});
CSS
.product-x, .product-y{
width:100px;
height:50px;
margin:10px;
}
.product-x{
border:red 1px solid;
}
.product-y{
border:navy 1px solid;
}
HTML
<div id="product-x-wrapper">
<div class="product-x">1
<button class="delete-item">x</button>
</div>
<div class="product-x">2
<button class="delete-item">x</button>
</div>
<div class="product-x">3
<button class="delete-item">x</button>
</div>
</div>
<div id="product-y-wrapper">
<div class="product-y">1
<button class="delete-item">x</button>
</div>
<div class="product-y">2
<button class="delete-item">x</button>
</div>
<div class="product-y">3
<button class="delete-item">x</button>
</div>
</div>

First, I would add a data-product-id to each element so you can find them without relying on the human-readable label:
<div id="product-wrapper">
<div class="product-x" data-product-id="1">1 <button...></div>
<div class="product-x" data-product-id="2">2 <button...></div>
<div class="product-x" data-product-id="3">3 <button...></div>
<div class="product-y" data-product-id="1">1 <button...></div>
<div class="product-y" data-product-id="2">2 <button...></div>
<div class="product-y" data-product-id="3">3 <button...></div>
</div>
Then you can remove the matching sibling like this:
$(document).on('click', '.delete-item', function(e) {
var id = $(this).parent().data('product-id');
$("#product-wrapper").find('div[data-product-id="' + id + '"]').delay(500).remove();
});
EDIT: Since you've changed the question to separate the products into two wrappers, you can use this approach, but just remove things from both places, like so:
$(document).on('click', '.delete-item', function(e) {
var id = $(this).parent().data('product-id');
$("#product-x-wrapper").find('div[data-product-id="' + id + '"]').delay(500).remove();
$("#product-y-wrapper").find('div[data-product-id="' + id + '"]').delay(500).remove();
});

Without any additional markup or classes, you can use jQuery's .index() function to delete the corresponding item:
$('.delete-item').each(function() {
$(this).parent().data('idx', $(this).parent().index())
}).click(function() {
var idx = $(this).parent().data('idx');
$('div > div').each(function() {
if ($(this).data('idx') === idx) $(this).remove()
})
})
.product-x,
.product-y {
width: 100px;
height: 50px;
margin: 10px;
}
.product-x {
border: red 1px solid;
}
.product-y {
border: navy 1px solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="product-x-wrapper">
<div class="product-x">1
<button class="delete-item">x</button>
</div>
<div class="product-x">2
<button class="delete-item">x</button>
</div>
<div class="product-x">3
<button class="delete-item">x</button>
</div>
</div>
<div id="product-y-wrapper">
<div class="product-y">1
<button class="delete-item">x</button>
</div>
<div class="product-y">2
<button class="delete-item">x</button>
</div>
<div class="product-y">3
<button class="delete-item">x</button>
</div>
</div>

The way I would do this is grab the value of the product-y you have clicked on using jquerys .val(). Then you can loop through all your product-x's and once you have found a matching .val then you can delete that.
I can write you some code if you need but hopefully this is enough to help you understand how to solve it.
e/ - Pauls way is more elegant use that :D

you should probably just add an id to it so you can look it up by id, but assuming they are all corresponding and in order you can do this
$(document).on('click', '.delete-item', function(e) {
var producty = $(this).parent();
var index = $(".product-y").index(producty );
$('.product-x:eq('+ index +')').remove();
}
this also allows your html to differ

Quick Note: You should use some sort of DOM Handle which can be accessed using a selector, like class,id,data- attributes, name etc.
now if you still want to go this way, which I strongly discourage, then you can use the :contains selector.
$(document).on('click', '.delete-item', function(e) {
$content = $(this).parent().html();
$(this).parents('.product-x').delay(500).remove();
$(".product-y:contains("+$content+")).delay(500).remove();
});

Slightly different take:
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div data-product="one" class="one product-x">1
<button class="delete-item">x</button>
</div>
<div data-product="two" class="two product-x">2
<button class="delete-item">x</button>
</div>
<div data-product="three" class="three product-x">3
<button class="delete-item">x</button>
</div>
<div data-product="one" class="one product-y">1
<button class="delete-item">x</button>
</div>
<div data-product="two" class="two product-y">2
<button class="delete-item">x</button>
</div>
<div data-product="three" class="three product-y">3
<button class="delete-item">x</button>
</div>
<script type="text/javascript">
$('.delete-item').on('click',function(e){
var theProduct = $(this).parent().data('product');
var theElements = $('div[data-product="' + theProduct + '"]');
theElements.delay(500).fadeOut();
})
</script>
fadeOut() is sexier ;)

Related

Could I get to an element using two ids?

Here's my code:
<div id='layer1'>
<div id='a'>
<div id='b'>
<div id='layer2'>
<div id='a'>
<div id='b'>
<div id='layer3'>
<div id='a'>
<div id='b'>
I want to try to get the element [a] of layer1.
Could I do this using pure javascript and withOUT jquery and other stuff?
An ID uniquely identifies one single element on the page. The behavior you described is more like "a class" inside of an ID:
document.querySelector("#counter-for-drinks .up-arrow")
and so if you want a different up-arrow, it is:
document.querySelector("#counter-for-burgers .up-arrow")
document.querySelector() is what is similar to jQuery $(" "). It also has the form document.querySelectorAll() for getting all matched elements.
Your HTML is missing closing tags. You can always validate your code here.
Also, you should use class instead of id.
<div id='layer1'>
<div class='a'></div>
<div class='b'></div>
</div>
<div id='layer2'>
<div class='a'></div>
<div class='b'></div>
</div>
<div id='layer3'>
<div class='a'></div>
<div class='b'></div>
</div>
You can use javascript to get elements:
document.querySelector("#layer1 .a")
var firstA = document.querySelectorAll('#layer1 #a');
var nodeString = '';
if (firstA.length > 0) {
for (var i = 0; i < firstA.length; i++) {
nodeString = nodeString + firstA[i].innerText + '<br/>';
}
}
document.getElementById('founded-nodes').innerHTML = nodeString;
#founded-nodes {
color: brown;
}
<div id='layer1'>
<div id='a'>layer1 aaa</div>
<div id='b'>layer1 bbb</div>
</div>
<div id='layer2'>
<div id='a'>layer2 aaa</div>
<div id='b'>layer2 bbb</div>
</div>
<div id='layer3'>
<div id='a'>layer3 aaa</div>
<div id='b'>layer3 bbb</div>
</div>
<div id="founded-nodes"></div>
As all said in above over comments and answers, one must use a single id on the same page, or else the use of classes is a must. But if you want to achieve this, you can have a look at code.

How to get to specific element in jquery

I have HTML structureL
<div class="services-article-elements-single">
<div class="services-article-description">
<button class="services-article-read-more-btn">read more</button>
</div>
<div class="services-article-after-roll"></div>
</div>
I want after clicking a button something happen with my <div class="services-article-after-roll"></div>
So far, I have:
jQuery('.services-article-read-more-btn').click(() =>{
// ????????
})
I think the appropriate method is find() but I'm not sure
Just select your element. In this case, you can select you element by class. In my simple example, the button shows or hides a div.
$('.services-article-read-more-btn').click(function() {
$(".services-article-after-roll").toggle();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="services-article-elements-single">
<div class="services-article-description">
<button class="services-article-read-more-btn">My button</button>
</div>
<div class="services-article-after-roll">MY DIV</div>
</div>
EDIT: if you have a structure with more than one div with class services-article-elements-single, you can select a wrapper div using .closest() and then find the element inside that container using .find() function.
$('.services-article-read-more-btn').click(function() {
var elementWrapper = $(this).closest(".services-article-elements-single");
elementWrapper.find(".services-article-after-roll").toggle();
})
.services-article-elements-single {
padding: 10px;
margin: 10px;
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="services-article-elements-single">
<div class="services-article-description">
<button class="services-article-read-more-btn">My button</button>
</div>
<div class="services-article-after-roll">MY DIV</div>
</div>
<div class="services-article-elements-single">
<div class="services-article-description">
<button class="services-article-read-more-btn">My button</button>
</div>
<div class="services-article-after-roll">MY DIV</div>
</div>
<div class="services-article-elements-single">
<div class="services-article-description">
<button class="services-article-read-more-btn">My button</button>
</div>
<div class="services-article-after-roll">MY DIV</div>
</div>
jQuery itself is a function which allows selecting elements. You can just use jQuery('.services-article-after-roll') and you will get the element.
jQuery('.services-article-read-more-btn').click(() => {
const $servicesArticleAfterRoll = jQuery('.services-article-after-roll');
// ... do stuff
})
Assuming you have more than one 'roll', you'll need to use a context specific selector - that just means use this within the event handler:
$(".services-article-read-more-btn").click(function() {
$(this).closest(".services-article-elements-single")
.find(".services-article-after-roll")
.fadeIn();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="services-article-elements-single">
<div class="services-article-description">
<button class="services-article-read-more-btn">read more</button>
</div>
<div class="services-article-after-roll" style='display:none;'>more info</div>
</div>
<div class="services-article-elements-single">
<div class="services-article-description">
<button class="services-article-read-more-btn">read more</button>
</div>
<div class="services-article-after-roll" style='display:none;'>more info</div>
</div>
Where .closest finds the closest parent with that class (the containing div) and then .find goes back down within that div to find the related details.
To achieve what you require you can use DOM traversal. In the click handler you can use closest() to get the nearest common parent element to the one which raised the event and the one you want to target. Then you can use find() to get that element before amending it as required. In the example below I just toggle a class to hide/show them:
$('.services-article-read-more-btn').click(function() {
$(this).closest('.services-article-elements-single').find('.services-article-after-roll').toggleClass('show');
})
.services-article-after-roll {
display: none;
}
.services-article-after-roll.show {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="services-article-elements-single">
<div class="services-article-description">
<button class="services-article-read-more-btn">read more</button>
</div>
<div class="services-article-after-roll">After roll...</div>
</div>
<div class="services-article-elements-single">
<div class="services-article-description">
<button class="services-article-read-more-btn">read more</button>
</div>
<div class="services-article-after-roll">After roll...</div>
</div>

Change text in multiple divs with same class onclick [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have a list of football matches and would like to replace all scores with "?-?" when pressing a button and toggle back to show the score when pressing again.
div {
display: table;
}
div div {
display: table-row;
}
div div div {
display: table-cell;
}
.score {
color: blue;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Hide scores!</button>
<br> <br>
<div class="table">
<div class="match">
<div class="team1">Manchester United</div>
<div class="score">1-1</div>
<div class="team2">Liverpool</div>
</div>
<div class="match">
<div class="team1">Juventus</div>
<div class="score">2-0</div>
<div class="team2">Inter Milan</div>
</div>
<div class="match">
<div class="team1">Real Madrid</div>
<div class="score">1-4</div>
<div class="team2">Barcelona</div>
</div>
<div class="match">
<div class="team1">Dortmund</div>
<div class="score">3-0</div>
<div class="team2">Bayern Munich</div>
</div>
<div class="match">
<div class="team1">PSG</div>
<div class="score">0-1</div>
<div class="team2">Marseille</div>
</div>
</div>
I have experimented with getElementById and innerHTML, but due to the large number of matches I would prefer to use getElementsByClassName instead. I've seen people recommending querySelectorAll() for this, but I can't get the scripts to work.
An alternative would be to run a script replacing all numbers with a question mark inside divs with the same class.
Please help me out by using this fiddle
Here's a solution that uses querySelector only to select the button and the .table element to toggle a class.
The rest is all CSS, so no looping is needed.
Note that this exchanges your .score text content for a data-score attribute.
document.querySelector("button")
.addEventListener("click", function() {
document.querySelector("div.table").classList.toggle("hide-score");
});
.table .score:after {
content: attr(data-score);
}
.table.hide-score .score:after {
content: "?-?";
}
<button>Hide scores!</button>
<br>
<br>
<div class="table">
<div class="match">
<div class="team1">Manchester United</div>
<div class="score" data-score="1-1"></div>
<div class="team2">Liverpool</div>
</div>
<div class="match">
<div class="team1">Juventus</div>
<div class="score" data-score="2-0"></div>
<div class="team2">Inter Milan</div>
</div>
<div class="match">
<div class="team1">Real Madrid</div>
<div class="score" data-score="1-4"></div>
<div class="team2">Barcelona</div>
</div>
<div class="match">
<div class="team1">Dortmund</div>
<div class="score" data-score="3-0"></div>
<div class="team2">Bayern Munich</div>
</div>
<div class="match">
<div class="team1">PSG</div>
<div class="score" data-score="0-1"></div>
<div class="team2">Marseille</div>
</div>
</div>
To support older browsers, you could instead keep the score as text content, but put it in a span with another <span>?-?</span> next to it, and then configure the CSS to hide the :first-child and show the rest as needed.
If you don't want to change your html code
$.each($('.score'), function(key, score) {
var score_text = $(score).text();
$(score).data('score', score_text)
})
$('button').click(function() {
if ($(this).data('hiding-score')) {
$(this).data('hiding-score', false);
$.each($('.score'), function () {
$(this).text($(this).data('score'));
});
} else {
$(this).data('hiding-score', true);
$('.score').text('?-?');
}
})
div { display:table; }
div div { display:table-row; }
div div div { display:table-cell; }
.score { color:blue; padding:10px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Hide scores!</button>
<br>
<br>
<div class="table">
<div class="match">
<div class="team1">Manchester United</div>
<div class="score">1-1</div>
<div class="team2">Liverpool</div>
</div>
<div class="match">
<div class="team1">Juventus</div>
<div class="score">2-0</div>
<div class="team2">Inter Milan</div>
</div>
<div class="match">
<div class="team1">Real Madrid</div>
<div class="score">1-4</div>
<div class="team2">Barcelona</div>
</div>
<div class="match">
<div class="team1">Dortmund</div>
<div class="score">3-0</div>
<div class="team2">Bayern Munich</div>
</div>
<div class="match">
<div class="team1">PSG</div>
<div class="score">0-1</div>
<div class="team2">Marseille</div>
</div>
</div>
Here is a fiddle with plain old Javascript.
But I have to admit, #SkinnyPete's way is way better and easier to understand ! You shouls use it if you're only to hide the score. This is the best way to go.
// Mandatory JS code
const score = document.getElementsByClassName('score')
const button = document.getElementById("hide")
const initialState = []
for(let i = 0; i < score.length; i++){
initialState.push({initial : score[i].innerHTML})
}
button.addEventListener('click', (e) => {
const dynamicScore = document.getElementsByClassName('score')
for(let i = 0; i < dynamicScore.length; i++){
if(dynamicScore[i].innerText === initialState[i].initial){
dynamicScore[i].innerHTML = "?-?"
}else{
dynamicScore[i].innerHTML = initialState[i].initial
}
}
})
i added an id "hide" to your button this works fine
The solution I would recommend is that you make use of data attributes on the divs to store the scores. i.e. <div class="score" data-for="1" data-against="1">1-1</div>. Then it's easier to toggle the values. Since you're using jQuery,
// Set the values to ?-?
$('.match .score').html('?-?');
// set the actual scores
$('.match .score').each(function(){
$(this).html($(this).data('for') + '-' + $(this).data('against'));
});
My solution:
I would use the temporary storage. U can set the values for each element with the data()-Method
//STORE DATA IN TEMP STORAGE
$( ".score" ).each(function( index ) {
$(this).data("score-temp", $(this).text());
});
On Click-Event I would add a class "hide-score" to distinguish between both states. And if hide-score is already set, than you reset the values from the temporary storage
$("button").click(function() {
if ($(".table").hasClass( "hide-score" )) {
$(".table").removeClass("hide-score");
//set VALUE FROM TEMP STORAGE
$( ".score" ).each(function( index ) {
var score_temp = $(this).data("score-temp" );
$(this).text(score_temp);
});
}
else {
$( ".score" ).text("?-?");
$(".table").addClass("hide-score");
}
});

Edit css of "item" when clicking on corresponding "btn"

So I have this
<div class="btns">
<div class="btn1"></div>
<div class="btn2"></div>
<div class="btn3"></div>
<div class="btn4"></div>
</div>
<div class="prevs">
<div class="pre1"></div>
<div class="pre2"></div>
<div class="pre3"></div>
<div class="pre4"></div>
</div>
http://jsfiddle.net/uzpxjukv/
You have btn1, btn2, btn3 and btn4. I'm trying to make it so that when you press btn1, the div with the class pre1 should then get "display: block;" or something to make it visible. Then when btn2 is clicked, pre1 turns invisible again and pre2 turns visible.
Maybe something like this? If there will be more buttons, it should be more optimalized.
$('.btns').find('div').click(function(){
$('.prevs').find('div').eq($(this).index()).toggle();
});
$('.btns').find('div').click(function(){
$('.prevs').find('div').eq($(this).index()).toggle();
});
.prevs div:not(.pre1) {
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btns">
<div class="btn1">Button 1</div>
<div class="btn2">Button 2</div>
<div class="btn3">Button 3</div>
<div class="btn4">Button 4</div>
</div>
<div class="prevs">
<div class="pre1">Previews 1</div>
<div class="pre2">Previews 2</div>
<div class="pre3">Previews 3</div>
<div class="pre4">Previews 4</div>
</div>
JSFIDDLE DEMO -> http://jsfiddle.net/uzpxjukv/5/
$('.btns div').click(function() {
var classNumber = this.className.slice(-1);
$('.prevs div').hide();
$('.pre' + classNumber).show();
});
On click of the button div, first hide all the pre divs and then show only the relevant div.
Try it
$('.btns > div').on('click', function() {
var numberOfDiv = $(this).attr('class').slice('-1'),
prevs = $('.prevs');
prevs.find('> div').hide();
prevs.find('.pre' + numberOfDiv).show();
});
This example is with your html code, if is possible to change it, you can get a better code.
See the fiddle
I have changed your HTML a little bit..Changed the class attribute of the prevs divsti ids.
HTML
<div class="btns">
<div class="btn1" id="1" onClick="reply_click(this.id)"></div>
<div class="btn2" id="2" onClick="reply_click(this.id)"></div>
<div class="btn3" id="3" onClick="reply_click(this.id)"></div>
<div class="btn4" id="4" onClick="reply_click(this.id)"></div>
</div>
<div class="prevs">
<div id="pre1"></div>
<div id="pre2"></div>
<div id="pre3"></div>
<div id="pre4"></div>
</div>
JS
function reply_click(id) {
document.getElementById("pre" + id).style.display = "block";
}
Provided that you know what naming system the divs use, you could use something along these lines. (To see properly working, view using developer tool)
$('.btns div').on('click', function() {
var currClass = $(this).attr('class').slice(-1); //get end of number of div clicked
$('.prevs div').css('display', 'none'); //reset all divs to being hidden
$('.pre' + currClass).css('display', 'inline-block'); //show desired div
});
.btns div {
background-color: gray;
}
.btns div, .prevs div {
width: 2em;
height: 2em;
display: inline-block;
padding-right: 0.2em;
}
.prevs div {
background-color: red;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btns">
<div class="btn1"></div>
<div class="btn2"></div>
<div class="btn3"></div>
<div class="btn4"></div>
</div>
<div class="prevs">
<div class="pre1"></div>
<div class="pre2"></div>
<div class="pre3"></div>
<div class="pre4"></div>
</div>

Javascript click specific to ID

I have a div setup like so:
<div class="content">
<button class="show-comments" id="content1"></button>
</div>
<div class="comments-wrapper" id="comment1"></div>
<div class="content">
<button class="show-comments" id="content2"></button>
</div>
<div class="comments-wrapper" id="comment2"></div>
I have the following code:
$('.show-comments').click(function(e){
e.preventDefault();
$('.comments-wrapper').slideToggle('slow');
});
As you would assume, the code works but on a class basis. I'd like for it to open up only the .comments-wrapper of its associated id (i.e. open slideToggle comments2 if content 2 button is clicked and so on and so on).
How would I do this?
$('.show-comments').click(function(e){
e.preventDefault();
$(this).closest(".content").next('.comments-wrapper').slideToggle('slow');
});
Note that this is dependent on the .content element being immediately followed by the .comments-wrapper.
If you have access to modify the html itself, I would suggest adding a wrapper element and then doing the following to avoid the reliance on the exact order of elements:
<div class="wrapper">
<div class="content">
<button class="show-comments" id="content1"></button>
</div>
<div class="comments-wrapper" id="comment1"></div>
</div>
<div class="wrapper">
<div class="content">
<button class="show-comments" id="content2"></button>
</div>
<div class="comments-wrapper" id="comment2"></div>
</div>
$(this).closest(".wrapper").find('.comments-wrapper').slideToggle('slow');
This way, if you add an element between the .content and the .comments-wrapper it does not break the code.
You can do this:
$(this).parent("div").next('.comments-wrapper').slideToggle('slow');
This will find the related div of class .comments-wrapper and slide toggle.
And a fiddle: http://jsfiddle.net/xCJQB/
$('.show-comments').click(function (e) {
e.preventDefault();
var num = this.id.match(/\d+$/)[0];
$("#comment" + num).slideToggle('slow');
});
Demo ---> http://jsfiddle.net/7pkyk/1/
Use this context
$(this).closest('.comments').next('.comments-wrapper').slideToggle('slow');
If it is not the immediate element then you might try this as well
$(this).closest('.comments')
.nextAll('.comments-wrapper').first().slideToggle('slow');
you can add a common class to associate a button with a div.
html:
<div class="content">
<button class="show-comments group1" id="content1"></button>
</div>
<div class="comments-wrapper group1" id="comment1">1</div>
<div class="content">
<button class="show-comments group2" id="content2"></button>
</div>
<div class="comments-wrapper group2" id="comment2">2</div>
javascript:
$('.show-comments').click(function(e){
var associate = $(this).attr('class').match(/group\d+/).pop();
var selector = '.comments-wrapper.' + associate;
e.preventDefault();
$(selector).slideToggle('slow');
});
http://jsfiddle.net/uMNfJ/

Categories

Resources