Hide specific elements using jQuery and JavaScript - javascript

We have issues with our code:
function remove_single_entry_if_empty() {
$(".single-entry").each(function() {
var ids = $(this).attr('id');
let a = (ids);
for ( let i = 0; i < a.length; a++ ) {
let x = document.getElementById(a);
if ( x.getElementsByClassName('entry_times-wrapper').length === 1 ) {
var c = x.getElementsByClassName('entry_times-wrapper').length === 1;
x.style.display = 'none';
}
}
});
}
HTML Structure:
<div class="single-entry" id="9127">
<div class="entries_wrapper">
<div class="entry_times-wrapper">
<!-- this is where the <a> tags is. -->
</div>
</div>
</div>
We have an HTML tag with the class single-entry. This class exist multiple times but each with a unique ID specified. The class name called entry_times-wrapper (which is a child element of variable X) has also multiple <a> tags.
What we want to do: if all items in class entry_times-wrapper are hidden (with display none), then hide the single-entry class for only that specific ID. For now, this code as described above will actually hide all these single entries.
How can we do this correctly?

To achieve this you can use a single line of jQuery which selects all the .single-entry elements which contain a hidden .entry_times-wrapper and then hide them. Try this:
$('.single-entry:has(.entry_times-wrapper:hidden)').hide();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="single-entry" id="9127">
<div class="entries_wrapper">
<div class="entry_times-wrapper">
Visible...
</div>
</div>
</div>
<div class="single-entry" id="9128">
<div class="entries_wrapper">
<div class="entry_times-wrapper">
Not visible...
</div>
</div>
</div>
<div class="single-entry" id="9120">
<div class="entries_wrapper">
<div class="entry_times-wrapper">
Visible...
</div>
</div>
</div>

Here is a working demo with several <div>s and <a>s:
$("button").click(function(){ $(".single-entry").add("a").show();});
$(".entry_times-wrapper a").click(function(){ $(this).hide();checkVis();})
// this needs to be called every time an <a> element is hidden or made visible again:
function checkVis(){
$(".single-entry").each(function(){
$(this).toggle($(".entry_times-wrapper a:visible",this).length>0)
});
}
.single-entry {background-color:#ccc; padding:6px;
border: 1px black solid; margin: 4px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>show all links again</button><br>
<div class="single-entry" id="9127">
<div class="entries_wrapper">
<div class="entry_times-wrapper">
first link<br>
second link<br>
third link
</div>
</div>
</div>
<div class="single-entry" id="9128">
<div class="entries_wrapper">
<div class="entry_times-wrapper">
fourth link<br>
fifth link<br>
sixth link
</div>
</div>
</div>
<div class="single-entry" id="9129">
<div class="entries_wrapper">
<div class="entry_times-wrapper">
seventh link<br>
eighth link<br>
ninth link
</div>
</div>
</div>

Related

Have multiple elements under different divs disappear on hover

I have 2 grid divs, one with images and the other with a list of names. Each element within each of the divs corresponds to another within the other div (eg. .image-1 corresponds with .name-1).
When you hover over one of the elements, I want that element AND the corresponding element in the other div to both disappear.
For example, when you hover over "Name 1", I want that and the corresponding image to both disappear. Here's my general html setup:
<body>
<div class="wrapper">
<div class="picture-grid grid">
<div class="grid-box image-1">
<img src="images/image1.png" />
</div>
<div class="grid-box image-2">
<img src="images/image2.png" />
</div>
<div class="grid-box image-3">
<img src="images/image3.png" />
</div>
<div class="grid-box image-4">
<img src="images/image4.png" />
</div>
<div class="grid-box image-5">
<img src="images/image5.png" />
</div>
</div>
<div class="names-grid grid">
<div class="grid-box name-1">Name 1</div>
<div class="grid-box name-2">Name 2</div>
<div class="grid-box name-3">Name 3</div>
<div class="grid-box name-4">Name 4</div>
<div class="grid-box name-5">Name 5</div>
</div>
</div>
</body>
I'm sorry, I've been stuck on this for hours and would love some help! Here's a fiddle:
https://jsfiddle.net/8egpf1j3/
One solution using JQuery is to add data-* attributes to the HTML markup. In this approach we going to add a data-target attribute that will hold the class of the related element that should be hidden (with opacity: 0) when the current element is hovered. You can use JQuery.data() to work with data-* attributes. Check the next simplified example, from where I hope you can understand the underlying idea.
$(".grid-box").hover(
// Handler for hover-in.
function()
{
$(this).css("opacity", 0);
$($(this).data("target")).css("opacity", 0);
},
// Handler for hover-out.
function()
{
$(this).css("opacity", 1);
$($(this).data("target")).css("opacity", 1);
}
);
.grid-box {
width: 100px;
background-color: skyblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="picture-grid grid">
<div class="grid-box image-1" data-target=".name-1">
IMAGE 1
</div>
<div class="grid-box image-2" data-target=".name-2">
IMAGE 2
</div>
<div class="grid-box image-3" data-target=".name-3">
IMAGE 3
</div>
<div class="grid-box image-4" data-target=".name-4">
IMAGE 4
</div>
</div>
<hr>
<div class="names-grid grid">
<div class="grid-box name-1" data-target=".image-1">
Name 1
</div>
<div class="grid-box name-2" data-target=".image-2">
Name 2
</div>
<div class="grid-box name-3" data-target=".image-3">
Name 3
</div>
<div class="grid-box name-4" data-target=".image-4">
Name 4
</div>
</div>
</div>
You can do it this way, I suppose number of images and names is the same, and they are in the same order. Means image number one is first in its div, and name number one is first in its div.
//getting all pictures by <a> tag
var pictures = document.querySelector(".picture-grid").querySelectorAll("a");
//getting all names by <a> tag
var names = document.querySelector(".names-grid").querySelectorAll("a");
//attach reaction to "hover" event to all pictures and names
for (var i = 0; i < pictures.length; i++){
pictures[i].addEventListener("mouseenter", hide.bind(i));
names[i].addEventListener("mouseenter", hide.bind(i));
}
//run function on "hover" event, i = index of chosen image/name
function hide (){
var i = this;
pictures[i].style.opacity = 0;
names[i].style.opacity = 0;
}

Enclose whole div in an <a>

I have a div which I want to surround with an <a href>. I have the jQuery to add the <a href> after the div but I struggle to set it before and close it after the div.
This is the jQuery code I have:
$('.box_service').each(function() {
var link = $(this).html();
$(this).contents().wrap('');
});
It results in this HTML:
<div class="row">
<div class="box_service">
<a href="example.com">
<div class="inner-row"></div>
</a>
</div>
</div>
However my goal is this structure:
<div class="row">
<a href="example.com">
<div class="box_service">
<div class="inner-row"></div>
</div>
</a>
</div>
I can't enter the div before because there are more boxes in this row so I would add the <a href> to everything in there
The issue is due to your call to contents() which means you're wrapping the elements inside .box_service, not that element itself. Remove that method call.
Also note that each() is redundant, you can do what you require in a single line:
$('.box_service').wrap('');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<div class="box_service">
Box service #1
<div class="inner-row">Inner row #1</div>
</div>
</div>
<div class="row">
<div class="box_service">
Box service #2
<div class="inner-row">Inner row #2</div>
</div>
</div>
.content will wrap the contents of your div, you want to wrap the div with <a> so call wrap on the div not on contents.
$('.box_service').each(function() {
var link = $(this).html();
$(this).wrap('');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<div class="box_service">
<div class="inner-row"></div>
</div>
</div>
$('.box_service').each(function() {
var link = $(this).html();
$(this).wrap('');
});
You just need to remove contents() in between $(this).wrap() because contents() mean that you are wrapping the children of $(this).
Remove .contents() in order to wrap around each element with the class box-service:
$('.box_service').each(function() {
$(this).wrap('');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<div class="box_service">
<a href="example.com">
<div class="inner-row"></div>
</a>
</div>
</div>
$('.box_service').wrap('');

Getting value of internal div when outside div is clicked

I have the following: A bunch of button div's which each have unique info
<div class="button">
<div id="first">
Johny
</div>
<div id="second">
Dog
</div>
<div id="third">
Pasta
</div>
</div>
<div class="button">
<div id="first">
Bob
</div>
<div id="second">
Cat
</div>
<div id="third">
Noodles
</div>
</div>
.
.
.
I'm trying to make it so that when one of these buttons is clicked, i can check the values of the inner divs.
For instance
$('.button').on('click', function () {
// Check to see if the text of the 'first' div is
// johnny or bob or something else
});
First of all you cannot use same id for multiple elements in a page.So,Instead use class for that.Ex:
<div class="button">
<div class="first">
Johny
</div>
<div class="second">
Dog
</div>
<div class="third">
Pasta
</div>
</div>
<div class="button">
<div class="first">
Bob
</div>
<div class="second">
Cat
</div>
<div class="third">
Noodles
</div>
</div>
Now in the javascript:
$('.button').on('click', function () {
var first=this.getElementsByClassName("first")[0];//gets first element of this button
var second=this.getElementsByClassName("second")[0];
var third=this.getElementsByClassName("third")[0];
//Now you do what ever you want
});
Try $(this).children(":first").text() to get fist div's text
<script>
$('.button').on('click', function () {
if ($(this).find("#first").html().trim() == "Johny") {
console.log("The first div is Johny");
} else if ($(this).find("#first").html().trim() == "Bob") {
console.log("The first div is Bob");
}
});
</script>
How about giving each div its own click handler? (you will need unique ids for this to work properly)
<script type="text/javascript">
var bchildren = $('.button').children();
$(bchildren).click(function() {
console.log($(this).html());
});
}
</script>

How to Show a corresponding element of the clicked element?

Basically I have multiple elements A,B,C,... And they are all "connected" to A1,B1,C1,...
For simplicity and better understanding , lets say A,B,C are personal data about A1,B1,C1 persons (A1,B1,C1 are pictures of those persons).
html looks like :
<div class="personal_data">
<p class="A"> Ronnie </p>
<p class="B"> James </p>
<p class="C"> Dio </p>
</div>
<div class="persons">
<div>
<div>
<div class="A1"> img1 </div>
</div>
</div>
<div>
<div>
<div class="B1"> img2 </div>
</div>
</div>
<div>
<div>
<div class="C1"> img3 </div>
</div>
</div>
</div>
Yes , those divs that contain img are nested like that and the order must not be changed.
p elements are hiddenand are shown in personal_data window according to which person has been clicked.
How can I make it that when one picture is clicked its corresponding p element is shown and the rest of them are hidden , and when I click to another picture it shows another p element and hides previous , and so on?
I tried with jQuery two methods :
$(".A1").click(function () {
$(".A").show();
$(".B").hide();
$(".C").hide(); })
But I immediately abandoned it for obvious reasons. It's ugly and I have more than 3 persons so doing it for every person like this would not be a good practice.
$(".persons div").click(function () {
var index=$(".persons div").index(this);
$(".personal_data p").hide().eq(index).show(); })
Because I don't know all jQuery functions ( and all native javascript functions) I was amazed by the power of these but because of those nested images the index of A that corresponds to the A1 would be ok , but other indexes would not have their pair with persons because the number od divs are not equal , rather then "shifted" by +3. So I tweaked .personal_data with 2 empty p elements after A,B and C so the indexes would align. And it worked but I feel like I am violating something .
Is there a more elegant way for achieving this? I feel my problem is lack of knowledge of all functions that exist inside javascript (and jQuery).
Get the list of matching clickable elements, and the personal data, ahead of time (so we don't have to keep re-querying them):
var clickables = $('.persons > div > div > div[class]');
var data = $('.personal_data p');
Then, when clicked, get the index of the clicked thing in that list, rather than hunt through the DOM:
clickables.click(
function() {
data.hide(); // hide the others
var idx = clickables.index(this);
$(data[idx]).show();
}
);
var clickables = $('.persons > div > div > div[class]');
var data = $('.personal_data p');
clickables.click(
function() {
data.hide();
var idx = clickables.index(this);
$(data[idx]).show();
}
)
.personal_data p {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="personal_data">
<p class="A">Ronnie</p>
<p class="B">James</p>
<p class="C">Dio</p>
</div>
<div class="persons">
<div>
<div>
<div class="A1">img1</div>
</div>
</div>
<div>
<div>
<div class="B1">img2</div>
</div>
</div>
<div>
<div>
<div class="C1">img3</div>
</div>
</div>
</div>
Assuming that you will have this class structure in your page consistently, I did something by comparing the class names. If the class name of the clicked div contains the class name of the p element, then the p will be shown, otherwise they will be hidden :
$(".persons div").click(function () {
var myclassname = $(this).attr('class');
$(".personal_data p").hide().filter(function() {
return myclassname.indexOf($(this).attr('class')) >= 0); //if it contains
}).show();
});
Well, I don't like working with index's in lists. I prefer that you retrieve it when you mount it on the server-side with attributes and id's.
So try the following:
$(document).ready(function () {
$('.personal_data p').on('click', function (event) {
var theTarget = $(this).attr('data-detail');
$('.person-details').removeClass('show'); //remove this line in case you don't want only one at a time
$('#' + theTarget).addClass('show');
});
})
.person-details {
opacity: 0;
}
.person-details.show {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="personal_data">
<p class="A" data-detail="ronnie"> Ronnie </p>
<p class="B" data-detail="james"> James </p>
<p class="C" data-detail="dio"> Dio </p>
</div>
<div class="persons">
<div>
<div>
<div class="A1 person-details" id="ronnie"> img1 </div>
</div>
</div>
<div>
<div>
<div class="B1 person-details" id="james"> img2 </div>
</div>
</div>
<div>
<div>
<div class="C1 person-details" id="dio"> img3 </div>
</div>
</div>
</div>
All the styling or class you can customize. If you prefer showing or hiding , just change the removeClass to hide, and the addClass to show
If you want the oposite interaction :
$(document).ready(function () {
$('.person-details').on('click', function (event) {
var theTarget = $(this).attr('data-detail');
$('.personal_data p').removeClass('show'); //remove this line in case you don't want only one at a time
$('#' + theTarget).addClass('show');
});
})
.personal_data p {
opacity: 0;
}
.personal_data p.show {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="personal_data">
<p class="A" id="ronnie"> Ronnie </p>
<p class="B" id="james"> James </p>
<p class="C" id="dio"> Dio </p>
</div>
<div class="persons">
<div>
<div>
<div class="A1 person-details" data-detail="ronnie"> img1 </div>
</div>
</div>
<div>
<div>
<div class="B1 person-details" data-detail="james" > img2 </div>
</div>
</div>
<div>
<div>
<div class="C1 person-details" data-detail="dio"> img3 </div>
</div>
</div>
</div>

Create a div inside div with same class name

I have the following structure of my HTML code:
<div id="bb-bookblock" class="bb-bookblock">
<div class="bb-item">
<div class="bb-custom-side">
Hello
</div>
<div class="bb-custom-side">
<button id="add">Click Here to add The page</button>
</div>
</div>
<div class="bb-item">
<div class="bb-custom-side">
<p>This is first page</p>
</div>
<div class="bb-custom-side">
<p>Hello</p>
</div>
</div>
<div class="bb-item">
<div class="bb-custom-side">
<p>This is second Page</p>
</div>
<div class="bb-custom-side">
<p>This is last page</p>
</div>
</div>
</div>
When I click on button with id=add I want to create the a new div after the last bb-item div with same two div inside it having class name bb-custom-side.
I know how to create the div using createElement and it a class, but I don't know how to create the sub div inside that newly created div. Can I associate with the last child or similar concept?
So after click event I want my HTML to be something like this:
<div id="bb-bookblock" class="bb-bookblock">
<div class="bb-item">
<div class="bb-custom-side">
Hello
</div>
<div class="bb-custom-side">
<button id="add">Click Here to add The page</button>
</div>
</div>
<div class="bb-item">
<div class="bb-custom-side">
<p>This is first page</p>
</div>
<div class="bb-custom-side">
<p>Hello</p>
</div>
</div>
<div class="bb-item">
<div class="bb-custom-side">
<p>This is second Page</p>
</div>
<div class="bb-custom-side">
<p>This is last page</p>
</div>
</div>
<--Newly created div-->
<div class="bb-item">
<div class="bb-custom-side">
new div
</div>
<div class="bb-custom-side">
new div 2
</div>
</div>
</div>
Use clone() to create copy of div elements and append it to main div:
$("#add").click(function(){
var clonedDiv = $(".bb-item:last").clone();
clonedDiv = clonedDiv.find("div.bb-custom-side p").text("This is third Page");
$("#bb-bookblock").append(clonedDiv);
});
DEMO FIDDLE
NOTE: I just updated text for last div (This is third Page). You have to put it in loop to increase number.
Try this.
$('#add').on('click',function(){
$('.bb-item').eq(1).append($('.bb-item:last-child').html());
});
OR
$('#add').click(function(){
$('.bb-item').eq(1).append($('.bb-item:last-child').html());
});
Working Demo
You can try this.
$(document).ready(function () {
$("#add").click(function () {
$("#bb-bookblock").append('<div class="bb-item"><div class="bb-custom-side"> new div</div><div class="bb-custom-side">new div 2</div></div>');
});
});
DEMO
This may not appeal to everyone, but, personally, I tend to like "blank slates" for my cloning.
If it were me, I would do this:
var $baseItem = $("<div></div>").addClass("bb-item");
var $baseCustomSide = $("<div></div>").addClass("bb-custom-side");
$("#add").click(function(){
var $newItem = $baseItem.clone();
$newItem.append($baseCustomSide.clone().html("your_first_content_here"));
$newItem.append($baseCustomSide.clone().html("your_second_content_here"));
$("#bb-bookblock").append($newItem);
});
Unless there is a really good reason to reuse an existing element, I find you end up having to be a lot more complex to "scrub" the existing content from the clone . . . using a blank template always seems more clean to me.

Categories