$(this).closest not working when added to script - javascript

Hello I have a very basic script that moves the child <img> inside its <label> parent when you hover on and off the <label> element.
The issue is if you hover over one label. ALL images under ALL labels move.. This i do not want. I tried to solve this by adding $(this).closest to my function. But when $(this).closest code is added it breaks. If you remove (this).closest from my code it works fine but its affecting all of them instead of the single one being hovered over.
HTML
<div class="checkbox-cover images-true">
<div>
<label> <img></img> </label>
<label> <img></img> </label>
<label> <img></img> </label>
<label> <img></img> </label>
</div>
</div>
jQuery
$(".checkbox-cover.images-true>div>label").hover(
function () {
$(this).closest('img').stop().animate({top: '-200px'});
}, function (){
$(this).closest('img').stop().animate({top: '0'});
});

closest searches the DOM tree going up (ancestors), not down (descendants), what you really want is find instead.
$(".checkbox-cover.images-true > div > label").hover(
function () {
$(this).find('> img').stop().animate({top: '-200px'});
}, function () {
$(this).find('> img').stop().animate({top: '0'})
});
});
Lastly, as the comments suggest, you can shorten $(this).find('> img') with $('img', this), setting the "context" parameter.

Since img is a child of label here and closest is used to get the closest parent that matches the selector. Try this instead:
$(".checkbox-cover.images-true>div>label").hover(
function() {
$('img', this).stop().animate({top: '-200px'});
},
function() {
$('img', this).stop().animate({top: '0'});
}
);
Also, you can achieve this with CSS only like:
.images-true label img {
position: relative;
transition: all 1s ease 0s;
top: 0;
}
.images-true label:hover img {
top: -200px;
}
<div class="checkbox-cover images-true">
<div>
<label> <img src="http://via.placeholder.com/100x100"></img> </label>
<label> <img src="http://via.placeholder.com/100x100"></img> </label>
</div>
</div>
Just wanted to let you know about it and keep all your options open.

Related

How do I hide the closest element to the element that was clicked without jQuery?

I have a function that changes the src attribute of an icon when this one is clicked.
I also want it to hide the closest icon of the class fave_icon. I tried the following but it's not working:
function trash(event, trashcan){
event.stopPropagation();
if (trashcan.getAttribute('src') == "Iconos/tacho.png")
{
trashcan.src = "Iconos/warning.png"; //this works ok
var heart = trashcan.closest(".fave_icon");
heart.style.visibility = "hidden"
}
}
Basically I want to hide the closest element with class fave_icon to trashcan.
On the HTML I have this several times:
<button class="accordion">
<div>
<img src="Iconos/heart.png" onclick="fav(event,this);" alt="Fave" class="fave_icon">
</div>
<div>
<img src="Iconos/tacho.png" onclick="trash(event,this);" alt="Delete" class="delete_icon">
</div>
</button>
If fave_icon is a class then you have to place dot (.) before the class name as part of the selector.
Change var heart = trashcan.closest("fave_icon");
To
var heart = trashcan.closest(".fave_icon");
Based on the code and HTML you have provided you can do something like the following:
function trash(event, trashcan){
event.stopPropagation();
if (trashcan.getAttribute('src') == "Iconos/tacho.png"){
trashcan.src = "Iconos/warning.png"; //this works ok
var heart = trashcan.closest('button').querySelector('.fave_icon');
heart.style.visibility = "hidden";
}
}
<button class="accordion">
<div>
<img src="Iconos/heart.png" onclick="fav(event,this);" alt="Fave" class="fave_icon">
</div>
<div>
<img src="Iconos/tacho.png" onclick="trash(event,this);" alt="Delete" class="delete_icon">
</div>
</button>
From the trash icon, you go up a level to the div, select the previousElementSibling to get the heart's div, and then go down a level to the heart image itself.
Because the element is already included in the event target, you don't need to pass this. Or, even better, if you select the trash image first, you can avoid this entirely and use explicit variable names, which are easier to understand and debug.
But inline event handlers are essentially eval inside HTML markup - they're bad practice and result in poorly factored, hard-to-manage code. Seriously consider attaching your events with JavaScript, instead, eg: https://developer.mozilla.org/en/DOM/element.addEventListener
Another problem is that buttons should not have closing tags. Use a container element instead, like a div.
So, try something like this:
document.querySelectorAll('img[src="Iconos/tacho.png"]').forEach(img => {
img.onclick = () => {
const heartImg = img.parentElement.previousElementSibling.children[0];
heartImg.style.visibility = 'hidden';
};
});
<div class="accordion">
<div>
<img src="Iconos/heart.png" alt="Fave" class="fave_icon">
</div>
<div>
<img src="Iconos/tacho.png" alt="Delete" class="delete_icon">
</div>
</div>
you can add a class to the clicked element and use the general sibling combinator if the two items are adjacent.
document.getElementById("hide")
.addEventListener("click", (event) => {
event.target.classList.add('active');
}, false);
#hide.active~.element {
visibility: hidden;
}
#hide {
cursor: pointer;
}
.accordion {
padding: 15px;
background: lightgrey;
border-bottom: 1px solid grey;
}
.accordion div {
color: black;
margin-right: 20px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/icono/1.3.0/icono.min.css" rel="stylesheet" />
<div class="accordion">
<div class="icono-trash" id="hide"></div>
<div class="element icono-heart"></div>
</div>

How to use JQuery to detect Mouseover and add animation on dynamic item

I have a series of div's that get loaded dynamically. There ID is set when the page loads, and they all have the same class of "pp-post". When the user hovers over an item with class="pp-post" the 'p' items within that become visible.
I want to add a different animation for each of these 'p' tags when they become visible.
I have minimal experience with JQuery so I am wondering how I can detect which "pp-post" item is hovered and apply the animations to the 'p' tags.
As for the animations not sure yet what to use but it could be JQuery animations or maybe use animations.css and add a class to the p tags when visible.
HTML:
<div id="{post_id}" class="pp-post">
<div id="{post_id}" class="pp-post-item">
<p id="{post_id}" class="pp-post-title"></p>
<p id="{post_id}" class="pp-arrow-down"></p>
</div>
</div>
CSS:
.pp-post-title {
visibility: hidden;
}
.pp-arrow-down {
visibility: hidden;
}
.pp-post-item:hover > p {
visibility: visible;
}
how I can detect which "pp-post" item is hovered and apply the animations to the 'p' tags
You can use $(this) to get the hovered pp-post.
The code will look like
$('.pp-post').hover(function(){
$(this).animate({
//animation code
});
});
To make p tag visible,
$('pp-post').hover(function(){
$(this).find('p').animate({
//animation code
});
});
Instead of animation function, you can also use certain specific functions like fadeIn
Sample snippet
$(document).ready(function() {
$('.pp-post').hover(function() {
$(this).find('p').fadeIn(2000);
});
});
.pp-post p {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="pp-post">Hover
<p>Sample1</p>
</div>
<div class="pp-post">Hover
<p>Sample1</p>
</div>
<div class="pp-post">Hover
<p>Sample1</p>
</div>
<div class="pp-post">Hover
<p>Sample1</p>
</div>
<div class="pp-post">Hover
<p>Sample1</p>
</div>

Select <divs> within parent <div> using jQuery

I have a parent <div>, #amwcontentwrapper, which has a series of divs within it with their own classes and ids.
I want to use jQuery to select these child divs, and IF they have the class .amwhidden, do nothing, but if not, remove the .amwshown class and add the .amwhidden class.
This is what I have so far, but it is not working. I think it may be my selecting of the child divs within the parent.
Can anybody see any obvious problems? Thanks for your help.
if ($('#amwcontentwrapper > div').hasClass('amwhidden')){
} else {
$('#amwcontentwrapper > div').fadeIn(600, function(){
$('#amwcontentwrapper > div').removeClass('amwshown');
$('#amwcontentwrapper > div').addClass('amwhidden');
});
}
And here is the basic html that I am using:
<div class="amwshown" id="amwintro">
Intro Section, which should have the 'amwshown' class removed, and the
'amwhidden' class added, when the jQuery runs. Currently, this does not happen.
</div>
UPDATE: Using War10ck's solution in the comments below (i.e. $('#amwcontentwrapper > div.amwshown')) I have managed to get the classes changing as I wished. However, those which have had the .amwshown class removed and .amwhidden class added still show on the page, despite the CSS looking like this:
.amwhidden {
display:none;
}
.amwshown {
display:block;
}
Looking at the Dev Tools, it seems that, when the jQuery is run (on a click event) the classes are changing, but any classes which are having the .amwshown class added (thus displaying them on the page) are also having the a <style> tag added to them which makes them display:block;
When I then press another button, which should hide the aformentioned <div> to make way for another one, the class is being changed to .amwhidden, but that <style> tag is not being deleted, so even though it has the .amwhidden class, it is still on the page.
I've created a JSFiddle here, if anybody still wants to help!
`
$(document).ready(function() {
$('#buybutton').click(function() {
$('#amwcontentwrapper > div.amwshown').fadeIn(600, function() {
$(this).removeClass('amwshown').addClass('amwhidden');
});
if ($('#amwbuy').hasClass('amwshown')) {} else {
$('#amwbuy').fadeIn(600, function() {
$('#amwbuy').removeClass('amwhidden');
$('#amwbuy').addClass('amwshown');
});
}
});
$('#phdbutton').click(function() {
$('#amwcontentwrapper > div.amwshown').fadeIn(600, function() {
$(this).removeClass('amwshown').addClass('amwhidden');
});
if ($('#amwphd').hasClass('amwshown')) {} else {
$('#amwphd').fadeIn(600, function() {
$('#amwphd').removeClass('amwhidden');
$('#amwphd').addClass('amwshown');
});
}
});
});
#sidebar {
position: absolute;
left: 1%;
top: 1%;
font-size: 5em;
color: #000000;
width: 10%;
display: block;
background-color: red;
}
#amwcontentwrapper {
position: absolute;
left: 20%;
top: 5%;
}
.amwshown {
display: block;
}
.amwhidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="amwsidebar">
<span class="sidebarbutton" id="phdbutton">PhD Button</span>
<br />
<br />
<span class="sidebarbutton" id="buybutton">Buy Button</span>
</div>
<div id="amwcontentwrapper">
<div class="amwshown" id="amwintro">
<p>An intro section to welcome the visitor. Disappears when one of the other sections is clicked.</p>
<br />
<br />
</div>
<div class="amwhidden" id="amwbuy">
Buy Section
</div>
<div class="amwhidden" id="amwphd">
PhD Section
</div>
</div>
`
You can use not to remove the elements you do not want, like this:
$('#amwcontentwrapper > div').not('.amwhidden')
.removeClass('amwshown')
.addClass('amwhidden');
And work with that.
Try this
$(document).ready(function() {
$("#amwcontentwrapper").children().each(function(elem, x) {
if ($(x).attr("class") == "amwhidden") {
alert($(x).attr("class"));
$(x).removeClass("amwhidden").addClass("amwshow");
alert($(x).attr("class"));
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="amwcontentwrapper">
<div class="amwhidden"></div>
<div></div>
<div></div>
</div>
You can try each as follow,
$("#amwcontentwrapper div").each(function(){
if($(this).hasClass('amwhidden'))
//DO something
else
//DO something
});
Thank you for all help, it has prompted some brainstorming which has solved this issue.
Instead of adding the .amwhidden class and removing the .amwhidden class using jQuery, I have just created a .amwsection class, which all the sections belong to which has an initial display value of none. So far, so good; all of the sections are not there when you load up the page.
Then I use the .css jQuery function to change the display:none to display:block when the corresponding button is clicked, and changing all other .amwsections to display:none. This works just fine, but the effect is quite abrupt; there is no fading in, as you would get if you used the .animate function. .animate, however, does not work with the display value.
.fadeOut and .fadeIn to the rescue! By wrapping the .css change in these, I can create a fading in/out effect and can still use the display value.
Here is one example of this code.
The #buybutton is the button to be pressed.
#amwintro is just something which appears when the page loads - it will now be set to display:none if this is the first button pressed.
The .amwsection are all of the hidden sections. This portion of the code just resets all of them. This and the #amwintro section happen very quickly (1/100th of a second) to keep response time good.
The #amwbuy is the specific section that I want to reveal. As you can see, this fades in over a longer period.
Currently only tested in Chrome, but I think I've got it!
$(document).ready(function () {
$('#buybutton').click(function() {
$('#amwintro').fadeOut(1, function() {
$(this).css({
display:'none',
});
});
$('.amwsection').fadeOut(1, function() {
$(this).css({
display:'none',
});
});
$('#amwbuy').fadeIn(600, function() {
$(this).css({
display:'block',
});
});
});
});

Targeting previous div in javascript or css

HTML code:
<div class="content">
<textarea> hello.png </textarea>
</div>
<div class="content-btn">
Click me
</div>
Javascript code:
$(".button").click(function() {
if ($(this).parent().previousSibling('.content').css('display') == 'none'){
$('.content').hide();
$(this).parent().previousSibling('.content').show();
}else {
$('.content').hide();
}
});
How would I go about only showing the textarea when 'Cick me' is clicked or hovered preferably in css but if not javascript. Thanks guys
https://jsfiddle.net/uway5hhg/8/
As exercise you could do this effect in pure css (using :target pseudoclass and a long delay in a simple transition) if you add a close button just below the textarea
http://codepen.io/anon/pen/JYoMRK
<div class="content" id="text">
<textarea> hello.png </textarea><br />
Close
</div>
<div class="content-btn">
Open
</div>
CSS
#text {
overflow: hidden;
height: 0;
opacity: 0;
transition: opacity 0s 999999s;
}
#text:target {
opacity: 1;
height: auto;
transition-delay: 0s;
}
#text:target ~ div a.button { display: none; }
Anyway if you look for a straight jQuery approach, a simple toggle() is enough (you might have to hide the .content element via css depending on the initial condition of your textarea)
https://jsfiddle.net/uway5hhg/39/
$(".button").click(function() {
var content = $(this).parent().prev('.content');
content.toggle();
});
As far as I know there is no way to catch previous sibling in CSS.
But it works with jQuery, here is your slightly changed code:
$(".button").on('click', function() {
var ele = $(this),
par = ele.parent(),
sbl = par.prev();
if (sbl.css('display') == 'none'){
$('.content').hide();
sbl.show();
}else {
$('.content').hide();
}
});
Working example is here: https://jsfiddle.net/y0ab3n0L/
That should do it's job
JS:
$(".button").click(function() {
var contentBtn = $(this).parent(".content-btn");
var content = $(contentBtn).prev(".content");
var textarea = $(content).find("textarea");
$(textarea).toggle();
});
or event shorter:
$(".button").click(function() {
$(this).parent(".content-btn").prev(".content").find("textarea").toggle();
});
https://jsfiddle.net/uway5hhg/21/
Hope this helps :)
Solution provided by Fabrizio is a good one if you want no javascript.
However you can also modify the DOM to have a similar effect.
<div class="content-wrapper">
<div class="content" id="text">
<textarea>hello.png</textarea>
</div>
Click me
</div>
CSS
.content {
display:none;
}
.content-wrapper:hover .content {
display:block;
}
.content-wrapper:hover .button {
display:none;
}
https://jsfiddle.net/2Lsszgqz/
There is no such CSS pseudo element - a.button:click, so only JS solution will work (without changing your HTML structure). You can also get to close of it using :focus CSS pseudo class. But you will lack to go up one level in CSS and then show the textarea. So, only solution left is using JS.
In your sample JS code you have used .previousSibling('.content') which is native JS, which you are calling on jQuery object, that's why it will not work. jQuery equivalent of this function is .prev('.content')
Correct Syntax would be -
$(".button").click(function() {
if ($(this).parent().prev('.content').css('display') == 'none'){
$('.content').hide();
$(this).parent().prev('.content').show();
}else {
$('.content').hide();
}
});
Working Fiddle

elim clicked <label> <div> <checkbox>

Below is a jsfiddle link that has got the code in it that needs modifying.
http://jsfiddle.net/N44Ah/
This is HTML code within the above jsfiddle link
<label for="cb">
<div id="clickablediv">
<input name="cb" id="cb" type="checkbox"/>
</div>
</label>
<label for="cb">
<div id="clickablediv">
<input name="cb" id="cb" type="checkbox"/>
</div>
</label>
This is the javascript within the above jsfiddle link
$('#clickablediv').click(function () {
if ($(this).find('#cb').is(':checked')) {
$(this).animate({
opacity: 0.5
}, 250);
} else {
$(this).animate({
opacity: 1
}, 250);
}
});
and this is the basic CSS
#clickablediv {
width: 100px;
height: 100px;
background: blue;
}
Basically I can't changed the div id, class or details as they are created from php after a database query what pulls an array and then fills each div with the required info for that div and then populates the next div until all information has been displayed in different divs.
I understand it is the javascript that needs to be modified here but I am just unsure on how to do it as I am not any good at javascript.
I need the effect to be so what ever div you click is the div that is effected because at the minute what ever div you click it only effects the top div.
once again I can't changed the div's id, class or details.
This maybe un-relevant but I did have the same sort of issue when I was creating buttons and hidden divs in the same way except when clicking the buttons it needed to display the correct div tied to it however in the above question I need to do a dim effect as what you can see in the js above.
below is the jsfiddle link to the code about the buttons and hidden divs using a (elim) function in javascript I am not sure if the same sort of elim method needs to be adopted for my new problem I am having.
http://jsfiddle.net/gpDFc/
I have tried to mess around with the both javascripts but as I am no good I didn't managed to make a working script.
Thank you for your time in reading this and I look forward to yuor help.
ID of an element must be unique.
The ID selector will return the first element with the said id, so your code will attach the click handler only to the first div with id clickablediv not to the second
Since you have repeated at least twice that the id cannot be changed, use an attribute selector to select the div's with the said id.
$('div[id="clickablediv"]').click(function () {
if ($(this).find('[name="cb"]').is(':checked')) {
$(this).animate({
opacity: 0.5
}, 250);
} else {
$(this).animate({
opacity: 1
}, 250);
}
});
Distinct Values required in DOM
See here, modified fiddle:
http://jsfiddle.net/N44Ah/1/
Use class instead of id like below. For entire page you can use single id. If you have multiple id with same name, first id only will be affected.
<label for="cb">
<div class="clickablediv">
<input name="cb" id="cb" type="checkbox"/>
</div>
</label>
<label for="cb">
<div class="clickablediv">
<input name="cb" id="cb" type="checkbox"/>
</div>
</label>
$('.clickablediv').click(function () {
if ($(this).find('#cb').is(':checked')) {
$(this).animate({
opacity: 0.5
}, 250);
} else {
$(this).animate({
opacity: 1
}, 250);
}
});
.clickablediv {
width: 100px;
height: 100px;
background: blue;
}

Categories