jQuery closest() appears to find parent id when there is none - javascript

I have an event listener for when the user clicks in the window. I want to see if the clicked element has any parent element with a certain id. I use the jQuery closest() function for that. But it always returns true.
Here is a fiddle that demonstrates my code.
There must be some major error, because if I change the id from if($(event.target).closest('#activatemenu'))
into any other id
if($(event.target).closest('#rrrrrrr'))
it still returns true.
Code in fiddle:
$(function() {
$(document).click(function(event) {
if($(event.target).closest('#activatemenu')) {
$('.wrap').prepend('<p>the clicked element has a parent with the id of activatemenu</p>');
}else{
$('.wrap p').remove();
}
});
});
.stuff{
width:300px;
height:150px;
border:red 2px solid;
}
.otherstuff{
width:400px;
height:400px;
background:purple;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
<div id="activatemenu">
<div>
<div>
<div class="stuff">
<p>Here is some text</p>
</div>
</div>
</div>
</div>
<div class="otherstuff">
<p>Other stuff!</p>
</div>
</div>

Closest always returns a jQuery object which resolves to truthy. You need to check the length of the object.
$(event.target).closest('#rrrrrrr').length
Or, use
$(function() {
$(document).click(function(event) {
if ($(event.target).closest('#activemenu').length) {
$('.wrap').prepend('<p>the clicked element has a parent with the id of activemenu</p>');
} else {
$('.wrap p').remove();
}
});
});
.stuff {
width: 300px;
height: 150px;
border: red 2px solid;
}
.otherstuff {
width: 400px;
height: 400px;
background: purple;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
<div id="activemenu">
<div>
<div>
<div class="stuff">
<p>Here is some text</p>
</div>
</div>
</div>
</div>
<div class="otherstuff">
<p>Other stuff!</p>
</div>
</div>

$(event.target).closest('#activatemenu') will always return an object so if condition will always be true, better check for $(event.target).closest('#activatemenu').length
$(function() {
$(document).click(function(event) {
if($(event.target).closest('#activemenu').length) {
$('.wrap').prepend('<p>the clicked element has a parent with the id of activemenu</p>');
}else{
$('.wrap p').remove();
}
});
});
.stuff{
width:300px;
height:150px;
border:red 2px solid;
}
.otherstuff{
width:400px;
height:400px;
background:purple;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
<div id="activemenu">
<div>
<div>
<div class="stuff">
<p>Here is some text</p>
</div>
</div>
</div>
</div>
<div class="otherstuff">
<p>Other stuff!</p>
</div>
</div>

You have two problems with your code.
First, you need to search for the closest activemenu not activatemenu. activatemenu does not exist in your code.
Second, jQuery will always return an array so you need to check the length to see whether the element was found as a non-empty array will always return true.
See below for a working example:
$(function() {
$(document).click(function(evt) {
if($(evt.target).closest('#activemenu').length) {
$('.wrap').prepend('<p>the clicked element has a parent with the id of activemenu</p>');
} else {
$('.wrap p').remove();
}
});
});
.stuff {
width: 300px;
height: 150px;
border: red 2px solid;
}
.otherstuff {
width: 400px;
height: 400px;
background: purple;
}
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<div class="wrap">
<div id="activemenu">
<div>
<div>
<div class="stuff">
<p>Here is some text</p>
</div>
</div>
</div>
</div>
<div class="otherstuff">
<p>Other stuff!</p>
</div>
</div>

Related

How to correctly target by class name?

I am trying to practice some things on JS, I want to toggle a number of divs on click to change their color but I can't seem to target correctly the first one. It was fine when I did it by tag name but by class it doesnt seem to work. What am I doing wrong? Thanks!
EDIT. This is what my code looks like after your corrections.
<body>
<div class="container">
<div class="one">
</div>
<div class="two">
</div>
<div class="three">
</div>
<div class="four">
</div>
</div>
<script src="script.js"></script>
</body>
let boxOne = document.getElementsByClassName("one")[0]
boxOne.onclick = function() {
alert("Clicked!")
}
I'm going to add that its better to assign an id and use getElementById if the selector is only used by one element.
let boxOne = document.getElementById("one");
let allBoxes = document.getElementsByClassName("square");
boxOne.onclick = function() {
alert("Clicked via ID");
}
const arr = [1, 2, 3];
arr.forEach(i => {
allBoxes[i].onclick = function() {
alert("Clicked via Class");
}
})
.square {
width: 100px;
height: 100px;
background: blue;
margin: 20px;
font-size: 50px;
color: white;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
cursor: pointer;
}
<body>
<div class="container">
<div class="square" id="one">
1
</div>
<div class="square" id="two">
2
</div>
<div class="square" id="three">
3
</div>
<div class="square" id="four">
4
</div>
</div>
</body>
With this line:document.getElementsByClassName(".one")[0]
you are already targeting the div, so change out this:
boxOne[0].onclick =
to this:
boxOne.onclick =
document.
getElementsByClassName returns array of elements with that className (without dot)
querySelector is used for css selectors (eg. ".one", "div.one")
querySelectorAll like 2. but returns array
let boxOne = document.getElementsByClassName("one")[0]
boxOne.onclick = function() {
alert("Clicked!")
}
div {
width: 100px;
height: 100px;
margin: 30px;
background: blue
}
<body>
<div class="container">
<div class="one">
</div>
<div class="two">
</div>
<div class="three">
</div>
<div class="four">
</div>
</div>
<script src="script.js"></script>
</body>

How do I make one element appear without triggering other elements of the same class

I have to make a set of buttons that appear and disappear.
How it is supposed to work:
I click on link 1 (link 2 is invisible at this point).
link 2 should then appear.
the problem here is there can be multiple elements of the same type with the same classes and I can't figure out how to distinguish between just showing the "link2"
that corresponds to the clicked "link1" without triggering the other "link2".
there is some code showing the progress I have made.
thank you in advance!
<style>
.hideaction{
visibility: hidden;
}
.showaction{
visibility: visible;
}
</style>
<script>
$(document).ready(function(){
$(".elem_action_showing").click(function(){
$(".elem_action_hiding").removeClass("hideaction").addClass("showaction");
});
</script>
</head>
<body>
<div class="elem_card card_set_click" style=" border: 1px solid black">
<div class="elem_hidden">
<p class="hideaction elem_action_hiding">%link2%</p>
</div>
<div class="elem_showing ">
<p class="elem_action_showing set_click">%link1%</p>
</div>
</div>
<div class="elem_card card_set_click" style=" border: 1px solid black">
<div class="elem_hidden">
<p class="hideaction elem_action_hiding">%link2%</p>
</div>
<div class="elem_showing ">
<p class="elem_action_showing set_click">%link1%</p>
</div>
</div>
</body>
The solution should work irregardless of how many ".elem_card" and ".hideaction" elements are there.
The issue is because you're selecting all .elem_action_hiding elements. To fix this use DOM traversal to find only the one which is related to the .elem_action_showing which was clicked. Try this:
$(".elem_action_showing").click(function() {
$(this).closest('.elem_showing').prev().find(".elem_action_hiding").toggleClass("hideaction showaction");
});
.hideaction {
visibility: hidden;
}
.showaction {
visibility: visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="elem_card card_set_click" style=" border: 1px solid black">
<div class="elem_hidden">
<p class="hideaction elem_action_hiding">%link2%</p>
</div>
<div class="elem_showing">
<p class="elem_action_showing set_click">%link1%</p>
</div>
</div>
<div class="elem_card card_set_click" style=" border: 1px solid black">
<div class="elem_hidden">
<p class="hideaction elem_action_hiding">%link2%</p>
</div>
<div class="elem_showing ">
<p class="elem_action_showing set_click">%link1%</p>
</div>
</div>

change nextAll() individually jQuery

function func(x) {
var y = $("#" + (x.id));
//nextAll get the number at the end of their id -=1
//y.nextAll().attr('id', )
//
y.remove()
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="maindiv">
<div id="div1" onclick="func(this)">Lorem</div>
<div id="div2" onclick="func(this)">Ipsum</div>
<div id="div3" onclick="func(this)">Dolor</div>
<div id="div4" onclick="func(this)">Sit</div>
<div id="div5" onclick="func(this)">Amet</div>
</div>
How would I loop through every div after the selected div?
For example, if the user clicks on div2, div3 will have a function, along with div4 and div5.
You can use each to iterate the elements in the selection
function func(x) {
var y = $(x);
y.nextAll().each(function(index, element){
// do something
})
y.remove()
}
To catch only the divs after the clicked element:
function func(x) {
$(x).nextAll().remove();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="maindiv">
<div id="div1" onclick="func(this)">Lorem</div>
<div id="div2" onclick="func(this)">Ipsum</div>
<div id="div3" onclick="func(this)">Dolor</div>
<div id="div4" onclick="func(this)">Sit</div>
<div id="div5" onclick="func(this)">Amet</div>
</div>
An alternative is using Next Siblings Selector (“target selector ~ next siblings selector”)
$('[id^=div]').on('click', function() {
$(`#${$(this).attr('id')} ~ div`).fadeOut(function() {
$(this).remove()
});
});
[id^=div] {
border: 1px dashed lightgreen;
padding: 5px;
margin: 5px;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="maindiv">
<div id="div1">Lorem</div>
<div id="div2">Ipsum</div>
<div id="div3">Dolor</div>
<div id="div4">Sit</div>
<div id="div5">Amet</div>
</div>

Change parent-parents background on child hover

I have following HTML code:
.background {
width: 100%;
height: 800px;
margin: 0 auto;
background-image:url("backimage1.jpg");
background-size: cover;
}
<div class="background">
<div class="wrapper">
<div class="box1">
<span class="title">Pozitivan feedback naših klijenata i njihovih potrošača</span><br />
<span class="description">Vrhunski kvalitet naših proizvoda</span>
</div>
</div>
</div>
What I would like is to when hover on "box1"to change background-image to something else. I know that I can't do that with CSS, tried few things with JS, but seems like I'm only able to select parents element, not parents-parent element though. Any suggestions?
document.getElementsByClassName('') can be use to select element by class name.
<html>
<head>
<style>
.background {
width: 100%;
height: 800px;
margin: 0 auto;
background-image:url("backimage1.jpg");
background-size: cover;
}s
</style>
<script type="text/javascript">
function changeBgMouseOver() {
var x = document.getElementsByClassName("background");
x[0].style.backgroundImage = "url('backimage2.jpg')";
}
function changeBgMouseOut() {
var x = document.getElementsByClassName("background");
x[0].style.backgroundImage = "url('backimage1.jpg')";
}
</script>
</head>
<body>
<div class="background">
<div class="wrapper">
<div class="box1" onmouseover="changeBgMouseOver()" onmouseout="changeBgMouseOut()">
<span class="title">Pozitivan feedback naših klijenata i njihovih potrošaca</span><br />
<span class="description">Vrhunski kvalitet naših proizvoda</span>
</div>
</div>
</div>
</body>
</html>
Using jquery hover function - changing the background-color :
In your case you can try this with background-image css property
$(document).ready(function(){
$(".box1").hover(function(){
$(this).parent().css("background-color","coral");
}, function(){
$(this).parent().css("background-color","");
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="background">
<div class="wrapper">
<div class="box1">
<span class="title">Pozitivan feedback naših klijenata i njihovih potrošača</span><br />
<span class="description">Vrhunski kvalitet naših proizvoda</span>
</div>
</div>
</div>
Here is JQ solution for you it's pretty straightforward:
$(".box1").hover(function(){
$('.background').css("background", "url(https://placebear.com/200/300)");
}, function(){
$('.background').css("background", "url(https://placebear.com/300/300)");
});
.background {
width: 100%;
height: 800px;
margin: 0 auto;
background-image:url("https://placebear.com/300/300");
background-size: cover;
}
.box1 {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="background">
<div class="wrapper">
<div class="box1">
<span class="title">Pozitivan feedback naših klijenata i njihovih potrošača</span><br />
<span class="description">Vrhunski kvalitet naših proizvoda</span>
</div>
</div>
</div>
Just using ".closest()" should be fine, ".parent().parent()" could also be a solution.
$(document).ready(function(){
$(".box1").mouseover(function(){
$(this).closest(".background").css("background-image","url('anotherimage.jpg')");
});
});
$(document).ready(function(){
$(".box1").mouseover(function(){
$(this).parent().parent().css("background-image","url('anotherimage.jpg')");
});
});

Issue on Injecting Data Attribute to an existing Element

Can you please take a look at this demo and let me know why I am not able to inject clicked element attribute data data-css to data attribute of color-box? as you can see I am able to print it out in the console by
console.log(jQuery(this).data('css'));
But the
jQuery('.current-color').data('css', jQuery(this).data('css'));
is not setting the data attribute for target element .current-color
jQuery(".color").on('click', function() {
jQuery('.current-color').css('background', jQuery(this).data('color'));
jQuery('.current-color').data('css', jQuery(this).data('css'));
console.log(jQuery(this).data('css'));
jQuery('.current-color-name').text(jQuery(this).find('.color-name').text());
});
.color-box {
width: 100px;
height: 100px;
cursor: pointer;
background:#eee;
border:2px solid #444;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="current-color" data-css="">
<div class="color-box current-color-name">Orane</div>
</div>
<div class="colors">
<div class="color-box color" data-css="red.css" data-color="#f44336">
<div class="color-name">red</div>
</div>
</div>
Try to use .attr('data-anything') instead of .data('anything') It works here
$(".color").on('click', function() {
$('.current-color').css('background', $(this).attr('data-color'));
$('.current-color').attr('data-css', $(this).attr('data-css'));
console.log($(this).attr('data-css'));
$('.current-color-name').text($(this).find('.color-name').text());
});
.color-box {
width: 100px;;
height: 100px;
cursor: pointer;
background:#eee;
border:2px solid #444;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="current-color" data-css="">
<div class="color-box current-color-name"></div>
</div>
<div class="colors">
<div class="color-box color" data-css="red.css" data-color="#f44336">
<div class="color-name">red</div>
</div>
<div class="color-box color" data-css="orange.css" data-color="orange">
<div class="color-name">Orange</div>
</div>
<div class="color-box color" data-css="blue.css" data-color="blue">
<div class="color-name">Blue</div>
</div>
</div>
The reason why 'data-' atrribute could not work was that when you first used the $('..').data(' ') method to get the attribute value after you set it by
$('..').data(' ',' ') method,jquery stored the value so that when you clicked again,the value had not changed.
I thought reason was more important than solution for a developer.I hoped this could help.

Categories