jQuery: Update content on a summary DIV based on clicks from other DIV elements - javascript

I'm trying to learn JS and jQuery and I'm using a project to do this. I've been scratching my head for the last 4 hours trying to figure out how to do something and I'm completely stuck.
Basically I want to update a div's content based on clicks from other div's using HTML data- attributes on the ".blue". I have price and description fields. I have managed to collect the data from the first div no matter where I click but then can't get this updated correctly based on the DIV I click in.
I've tried multiple combinations of $(this) keyword to try and make this work but couldn't figure it out. I've searched these forums and found somewhat a solution but couldn't get it, I think my mind is just too overwhelmed with this.
Here's the one I looked at: Update content in div, on click of another div
I'm sure this must be super simple but I can't get my head around it today.
Here's my code:
var upload = $('.blue').data('target1');
var download = $('.blue').data('target2');
var price = $(this).data('price');
$(document).ready(function() {
$('.blue').on('click', function() {
$(upload).removeClass('hide');
$(download).removeClass('hide');
});
$('#price').text(price);
});
div {
margin:0;
padding:0;
}
.blue {
background-color: #ddddEE;
border: 1px solid black;
}
.blue:hover {
cursor: pointer;
background-color: #aaaaEE;
}
.red {
background-color: #EEdddd;
border: 1px solid black;
}
.bold {
font-weight: 600;
text-align: center;
}
.hide {
display:none;
}
#price {
font-size: 22px;
color: blue;
font-weight: 400;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-xs-3">
<div class="col-xs-12 blue" data-target1="#target1" data-target2="#target2">
<span>$</span><span data-price="300" id="1">300</span><br>
<p id="desc1" class="hide">Description 1</p>
<span>text here</span><br>
<span>text here</span><br>
<span>text here</span>
</div>
</div>
<div class="col-xs-3">
<div class="col-xs-12 blue" data-target1="#target3" data-target2="#target4">
<span>$</span><span data-price="600" id="2">600</span><br>
<p id="desc2" class="hide">Description 2</p>
<span>text here</span><br>
<span>text here</span><br>
<span>text here</span>
</div>
</div><div class="col-xs-3">
<div class="col-xs-12 blue" data-target1="#target5" data-target2="#target6">
<span>$</span><span class="prices" data-price="1200" id="3">1200</span><br>
<p id="desc3" class="hide">Description 3</p>
<span>text here</span><br>
<span>text here</span><br>
<span>text here</span>
</div>
</div>
<div class="col-xs-3">
<div class="col-xs-12 red">
<span class="bold">Summary</span><br>
<div id="target1" class="hide"><span>TARGET 1</span></div>
<div id="target2" class="hide"><span>TARGET 2</span></div>.
<div id="target3" class="hide"><span>TARGET 3</span></div>
<div id="target4" class="hide"><span>TARGET 4</span></div>
<div id="target5" class="hide"><span>TARGET 5</span></div>
<div id="target6" class="hide"><span>TARGET 6</span></div>
<span id="price" class=""></span>
</div>
</div>
Here is my fiddle: https://jsfiddle.net/rodcunha/qav9sn6n/42/
Thank you in advance for any help for this newbie.

To understand the cause of your problem, and how to solve it, you have to be careful in the present case of when the various instructions you've written are evaluated, and also how some of the jQuery instructions you use work.
First thing to note: the first three lines of your Javascript code are evaluated just after they have been read. So after they are evaluated, the state of your variables is as follows :
upload = '#target1'
download = '#target2'
price = undefined
Since these are the values used in the rest of the code, in all cases, you can see why it always shows what you expect for the first <div> only. To understand why, let's analyze the first line :
var upload =
$('.blue') [1]
.data('target1') [2]
[1] returns the jQuery collection containing the DOM <div> elements that have the blue class. So far, so good?
[2] returns the value associated with the data-target1 attribute of the first element of the jQuery collection (see documentation for the .data method)
What you probably want is for upload, download and price to contain the values of the data-* attributes corresponding to the <div> the user clicks on. You cannot know in advance which element the user will click on, so it does not make sense to read the values before the user clicks on anything. So you should read the values when the event is processed.
According to jQuery's documentation for the event handlers, this is the element the event is currently associated with. So your <div> element.
Now that you know that, you probably realized what you should do to correct your code. By moving your existing code around and making the smallest changes possible, you end up with the following working code.
$(document).ready(function() {
$('.blue').on('click', function() {
var upload = $(this).data('target1');
$(upload).removeClass('hide');
var download = $(this).data('target2');
$(download).removeClass('hide');
var price = $(this).find('[data-price]').data('price');
$('#price').text(price);
});
});

I'm not sure is this the behaviour you want, can you check it?
https://jsfiddle.net/rodcunha/qav9sn6n/42/
$(document).ready(function() {
$('.blue').click(function() {
var x = $(this).attr('data-target1');
$(x).removeClass('hide');
});
$('#price').text(price);
});
if You want to add or remove class hide clicking again on the div you can change the removeClass to toggleClass.

Replace you code by:
$(document).ready(function() {
$('.blue').on('click', function(e) {
$($(e.currentTarget).data('target1')).removeClass('hide');
$($(e.currentTarget).data('target2')).removeClass('hide');
$('#price').text($(e.target).parent().find('.price').data('price'));
});
});

Add a price class for every span data-price.
<span>$</span><span class="price" data-price="300" id="1">300</span><br>
HTML:
<div class="col-xs-3">
<div class="col-xs-12 blue" data-target1="#target1" data-target2="#target2">
<span>$</span><span class="price" data-price="300" id="1">300</span><br>
<p id="desc1" class="hide">Description 1</p>
<span>text here</span><br>
</div>
</div>
<div class="col-xs-3">
<div class="col-xs-12 blue" data-target1="#target3" data-target2="#target4">
<span>$</span><span class="price" data-price="600" id="2">600</span><br>
<p id="desc2" class="hide">Description 2</p>
<span>text here</span><br>
</div>
</div>
<div class="col-xs-3">
<div class="col-xs-12 blue" data-target1="#target5" data-target2="#target6">
<span>$</span><span class="prices price" data-price="1200" id="3">1200</span><br>
<p id="desc3" class="hide">Description 3</p>
<span>text here</span><br>
</div>
</div>
<div class="col-xs-3">
<div class="col-xs-12 red">
<span class="bold">Summary</span><br>
<!-- add 'summary' class for all div -->
<div id="target1" class="hide summary"><span>TARGET 1</span></div>
<div id="target2" class="hide summary"><span>TARGET 2</span></div>
<div id="target3" class="hide summary"><span>TARGET 3</span></div>
<div id="target4" class="hide summary"><span>TARGET 4</span></div>
<div id="target5" class="hide summary"><span>TARGET 5</span></div>
<div id="target6" class="hide summary"><span>TARGET 6</span></div>
<span id="price" class=""></span>
</div>
</div>
To get the current clicked div use currentTarget instead of target because currentTarget always return .blue contains div as event listner is set on '.blue' but target results can be different depending on your click position into .blue class div.
jQuery:
$(document).ready(function() {
$('.blue').on('click', function(e) {
var upload = $(e.currentTarget).data('target1');
var download = $(e.currentTarget).data('target2');
var price = $(e.target).parent().find('.price').data('price');
// add a new class 'summary' for all 'summary id div'.
// loop over all '.summary' class and add 'hide' class
$('.summary').each(function(index, item) {
// console.log(item);
$(item).removeClass('hide').addClass('hide');
});
$(upload).removeClass('hide');
$(download).removeClass('hide');
$('#price').text(price);
});
});
jsfiddle link: https://jsfiddle.net/sajibcse68/qav9sn6n/49/

Related

javascript function to selectively show and hide contents by Id

I am working on a project where I want to show page contents selectively.
Have buttons "next" and "previous"
contents are id-ed in a serial manner.
what I want to achieve is
at the first page loading, show the first content(id='item-0') and only show the "next" button since there is no previous content, and when click on "next" button, hide currently showing contents(id='item-0') and show all the contents that are in (id='item-1') and so forth, and do not show the "next" button when it's the last content.
this is what I got so far,
on the page I first load every contents with display: none; so, nothing's showing up of course. but I want to be able to show the first content(id="item-0") by changing the style display to inline-block. and then update the "which" that's in the "next" button onclick action to the next id which is id="item-1" and dynamically update this "which" whenever either "next" or "previous" buttons clicked.
// page when first loaded.
<div class="container p-0 m-0" id="item-0" style="display:none;">
<p>example data</p>
<img src="example.com/img.png">
<video src="abc.com/abc/def.mp4"></video>
</div>
<div class="container p-0 m-0" id="item-1" style="display:none;">
<img src="example.com/img-5.png">
<video src="abc.com/abc/def.mp4"></video>
<div class="row"><h1>ABCD</h1></div>
</div>
<div class="container p-0 m-0" id="item-2" style="display:none;">
<p>example data</p>
<p>example data 2</p>
</div>
<a class="btn" onclick="nextBtn('item-0','item-1')">Next</a>
<a class="btn" onclick="prevBtn('item-0',null)" style="display:none;">Prev</a>
So far I worked on:
function show_item(which) {
var element = document.getElementById(which)
element.style.display='inline-block';
}
function hide_item(which) {
var element = document.getElementById(which)
element.style.display='none';
}
function nextBtn(current_which, next_which) {
// e.g. current_which = "item-0", next_which = "item-1"
hide_item(current_which);
show_item(next_which);
}
function prevBtn(current_which, prev_which) {
// e.g. current_which = "item-1", prev_which = "item-0"
hide_item(current_which);
show_item(prev_which);
}
what I haven't figured out are:
how to update the current_which and next_which that go in to the "Next" and "Prev" buttons.
how to not show "Prev" button when the page is showing the first content, and how to now show "Next" button when the page is showing the last content.
I have prepared something for you. If it is not exactly what you are looking for, I hope it'll you give some general idea on how to achieve what you want.
var next = document.querySelector('.next');
var prev = document.querySelector('.prev');
var elements = document.getElementsByClassName('container')
//get the currentDiv ID
var currentDiv = 0;
//when next is clicked
next.addEventListener('click',function(){
//we first check if the viewed div is not the last one
if(currentDiv < 2){
//if not we remove the .active class
removeActive(currentDiv);
//increment the ID of the current ID
currentDiv += 1;
//and add .active class to the next DIV
addActive(currentDiv)
}
})
prev.addEventListener('click',function(){
//same thing with prev, we first test if the current div is not the first one
if(currentDiv > 0){
//if not we remove the .active class
removeActive(currentDiv);
//decrement the selected div
currentDiv -= 1;
//and add the .active class
addActive(currentDiv);
}
})
//below are 2 functions that handles the addActive & removeActive if the conditions are passed
function removeActive(currentDiv){
document.getElementById('item-'+currentDiv).classList.remove('active');
}
function addActive(currentDiv){
document.getElementById('item-'+currentDiv).classList.add('active');
}
.container.hide {
display: none;
}
.active {
display: block !important;
}
.btn {
cursor: pointer;
}
<div class="container active hide p-0 m-0" id="item-0">
<p>example data</p>
<h3>Image For Div 1</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Smart-Watch.jpg" width="100px" height="100px"/>
</div>
<div class="container hide p-0 m-0" id="item-1">
<p>example data</p>
<h3>Image For Div 2</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Wireless-Phone-Chargers.jpg" width="100px" height="100px"/>
</div>
<div class="container hide p-0 m-0" id="item-2">
<p>example data</p>
<h3>Image For Div 3</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Phone-Lenses.jpg" width="100px" height="100px"/>
</div>
<br/><br/><br/>
<a class="btn prev">Prev</a>
<a class="btn next">Next</a>
Here is a slightly more condensed version of a working script:
const btn = document.querySelectorAll('.btn'), // btn[0]: Prev, btn[1]: Next
divs = document.querySelectorAll('.container');
function render(n){
[n,n!==divs.length-1].forEach((c,i)=>btn[i].style.visibility=c?null:"hidden"); // show/hide buttons
divs.forEach((d,i)=>d.classList.toggle("hide",i!==n)); // show/hide divs
}
render(divs.curr=1); // define the starting div
btn.forEach(b => b.onclick = () => {
render( divs.curr += (b.textContent==="Next" ? 1 : -1) );
});
.hide { display: none; }
.btn { cursor: pointer; }
<div class="container hide p-0 m-0" id="item-0">
<p>example data</p>
<h3>Image For Div 1</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Smart-Watch.jpg" width="100px" height="100px" />
</div>
<div class="container hide p-0 m-0" id="item-1">
<p>example data</p>
<h3>Image For Div 2</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Wireless-Phone-Chargers.jpg" width="100px" height="100px" />
</div>
<div class="container hide p-0 m-0" id="item-2">
<p>example data</p>
<h3>Image For Div 3</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Phone-Lenses.jpg" width="100px" height="100px" />
</div>
<div class="container hide p-0 m-0" id="item-3">
<p>example data</p>
<h3>Image For Div 4</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Thumb-224.jpg" height="100px" />
</div>
<div class="container hide p-0 m-0" id="item-4">
<p>example data</p>
<h3>Image For Div 5</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Thumb-221.jpg" height="100px" />
</div>
<br/><br/><br/>
<a class="btn prev">Prev</a>
<a class="btn next">Next</a>
I designed the script to have a small footprint, i. e. only a few global variables - or better - constants: btn and divs. In divs.curr you will find the index of the currently "active" div.
This script is also open for changes to the markup: The number of divs can change to any number.

How to make multiple divs appear one after the other using javascript?

I'm trying to animate a chat. Every time the user clicks on the input field or "send" icon, I want the chat bubbles to appear one after the other. This is my part of my code so far. Right now, they all have "display: none." The picture below shows them without it.
<div class="messages">
<div class="message" id="msg1" style="display: none;">Hi! I'm looking for an old friend. She attended Martin Grove a few years ago.</div>
<div class="message" id="msg2" style="display: none;">Her name is Sam.<br>
<i>*insert pic of Sam and MC*</i></div>
<div class="message" id="msg3" style="display: none;">Did you know her or her last name by any chance? </div>
<div id="msg4" class="message-teacher" style="display: none;">Hello there!</div>
<div class="message-teacher" id="msg5" style="display: none;">Unfortunately, I did not have the pleasure of teaching Sam. Her last name and whereabouts are a mystery to me as well. </div>
<div class="message-teacher" id="msg6" style="display: none;">However, I do know she was in the photography club. I always saw her carrying a camera, always taking pictures. </div>
<div class="message-teacher" id="msg7" style="display: none;">In fact, I believe she won a contest for one of them. </div>
<div class="message-teacher" id="msg8" style="display: none;">She’s a super talented girl!</div>
<div class="message-teacher" id="msg9" style="display: none;">Best of luck on your search. I hope you two are reunited soon!</div>
</div>
<div class="input">
<div class="plus-icon" style="font-size: 25px; color: #2A84FF; margin: auto;">
<i class="fas fa-plus-circle"></i>
</div>
<div class="subinput" style="font-size: 25px; color: #2A84FF; margin: auto;">
<input type="text" placeholder="|" />
<i class="fas fa-smile"></i>
</div>
<div class="btn" style="font-size: 23px; color: #2A84FF; margin: auto;"><i class="fas fa-paper-plane"></i></div>
</div>
I would query for the required elements, create an array out of it, and shift() (aka remove the first element of the array - or you can use pop() to remove the last element, depending on your needs). When you pop or shift an element from an array, those functions return the removed element and we can remove the CSS class that hides those elements in the DOM.
const myHTMLCollection = document.getElementsByClassName("invisible");
const HTMLElementsArr = [...myHTMLCollection];
function showMessage() {
if (HTMLElementsArr.length > 0) {
HTMLElementsArr.shift().classList.remove('invisible');
}
}
.invisible {
display: none;
}
<p class="invisible">Some text 1 click</p>
<p class="invisible">Some text 2 clicks</p>
<p class="invisible">Some text 3 clicks</p>
<button onClick="showMessage()">Show a message</button>

DOM traversing using jQuery

I am trying to create a comparison overlay that shows items selected by users when they 'add to compare' link.(like one in flipkart that appears on top when you hit add to compare). Here is my code:
<div class="college-list-container">
<div class = "individual-college-container" id="text1">
<div class="image-header"><h3>text1</h3>
</div>
<div class="dark-overlay">
<div class="overlay-links" style=" float:left;"> <div class="absolute-center ">Details</div></div>
<a href=""> <div class="overlay-links" style=" float:right; border-right:none;"> <div class="absolute-center comparison" id="comparison">Add to compare</div>
</div></a>
</div>
</div>
<div class = "individual-college-container">
<div class="image-header"><h3>text2</h3>
</div>
<div class="dark-overlay">
<div class="overlay-links" style=" float:left;"> <div class="absolute-center ">Details</div></div>
<a href=""> <div class="overlay-links" style=" float:right; border-right:none;"> <div class="absolute-center comparison">Add to compare</div>
</div></a>
</div>
</div>
<div class = "individual-college-container" id="itm">
<div class="image-header" ><h3>text3</h3>
</div>
<div class="dark-overlay">
<div class="overlay-links" style=" float:left;"> <div class="absolute-center ">Details</div></div>
<a href=""> <div class="overlay-links" style=" float:right; border-right:none;"> <div class="absolute-center comparison">Add to compare</div>
</div></a>
</div>
Javascript
/show overlay when one checkbox is checked and add its name/image to the empty space
$('.comparison').click(function(e){
var clgId = $(this).parentsUntil('.individual-clg-container').find('.image-header').text();
e.preventDefault();
var clg = $("<li></li>")
clg.text(clgId);
var removeLink = $("<a href=''>(Remove)</a>");
clg.append(removeLink)
$('.comparison-colleges').append(clg);
$('.add-to-compare-overlay').show("slide", { direction: "up" }, 300);
});
I want the text in the div containing class 'image-header' to be assigned to the variable clgId. The problem that i am facing with my code is that it is adding the text of all the divs containing class 'image-header'. Ex i want the value text1 to be assigned on clicking add to compare of the div with id text1. However it assigns 'text1 text2 text3' to clgId.
Please help
I've created a JSFiddle with what I think is your desired functionality (I included a console log output in the script of the clgId variable):
http://jsfiddle.net/py38kuvv/
I replaced the parentsUntil function with the closest function (and replaced the individual-clg-container class selector):
var clgId = $(e.target).closest('.individual-college-container').find('.image-header').text();
and also updated your click handler:
$('.comparison').on( "click", function(e) {
In order to get a quicker response in future, posting a JSFiddle of what you have so far makes it easier for others to help :)
It is adding all of them because
var clgId = $(this).parentsUntil('.individual-clg-container').find('.image-header').text();
should be
var clgId = $(this).parentsUntil('.individual-college-container').find('.image-header').text();

Find a specific class under a div to process child elements

Allow me to paste the HTML first that I am hoping to process.
<div class="top-box-part">
<h3 class="video-link-on-search">
My Title
<div style="display: none;">
<div id="colorbox-inline-1449860223">
<div class="jwplayer-video">...</div>
</div>
</div>
</h3>
<h3 class="search-title">My Another Title</h3>
</div>
<div class="top-box-part">
<h3 class="video-link-on-search">
My Title 2
<div style="display: none;">
<div id="colorbox-inline-1449860223">
</div>
</div>
</h3>
<h3 class="search-title">My second another title</h3>
</div>
As you can see there are two <h3> in the div. What I am hoping to do is, to show one <h3> in main div top-box-part. If the first <h3 class='video-link-on-search'> has jwplayer-video in it, then show this , and hide the second <h3 class='search-title'>, otherwise, hide the first h3 class='video-link-on-search' and show the second <h3 class='search-title'>.
There are many <div class='top-box-part'> in the page and each is with two <h3>. We only have one to show one <h3> in each.
Check with find()
$('.top-box-part').each(function() {
$(this).find('h3').hide();
if ($(this).find('h3 .jwplayer-video').length) {
$(this).find('h3:first').show();
} else {
$(this).find('h3:not(:first)').show();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="top-box-part">
<h3 class="video-link-on-search">
My Title
<div style="display: none;">
<div id="colorbox-inline-1449860223">
<div class="jwplayer-video">...</div>
</div>
</div>
</h3>
<h3 class="search-title">My Another Title</h3>
</div>
<div class="top-box-part">
<h3 class="video-link-on-search">
My Title 2
<div style="display: none;">
<div id="colorbox-inline-1449860223">
</div>
</div>
</h3>
<h3 class="search-title">My second another title</h3>
</div>
The proper selectors would be:
Every first h1 in every top_box-part:
var firsts = $('.top-box-part h3:nth-child(1)');
Every second h1 in every .top-box-part:
var seconds = $('.top-box-part h3:nth-child(2)');
Now you can simply check that like:
$.each(first,function(i,o){
var first_element_of_current_top_box = o;
var second_element_of_current_top_box = seconds[i];
// here you can compare anything and do anything with those elements (ex. `.hasClass` etc.)
});
Please note that this way needs 1st and 2nd H1 to be there!

How do I move identical elements from one div to another with jQuery?

With the example below, I'd like to select the contents of the < h3 > tags for each block, and move them inside the 'title' divs (without the h3 tags). Is this possible?
<div id="block1">
<div class="title">
</div>
<div class="content">
<h3>Title 1</h3>
</div>
</div>
<div id="block2">
<div class="title">
</div>
<div class="content">
<h3>Title 2</h3>
</div>
</div>
Online demo: http://jsbin.com/ezuxo
// Cycle through each <div class="content"></div>
$(".content").each(function(){
// Find its first h3 tag, and remove it
var heading = $("h3", this).remove();
// Set the text of the h3 tag to the value of the previous div (.title)
$(this).prev().html($(heading).html());
});
First off, I'd assign a class to the "blocks", let's call it "block" for now. Then do this:
$(".block").each(function() {
$(".title", this).html($(".content h3", this).html());
}

Categories

Resources