Mouseenter mark only one active node in hierarchy - javascript

I have several nested div-s and I would like to mark only one of them active when the mouse is over that element. The following code isn't work for every situation.
Code sample:
Red -> container
Green -> outer
Yellow -> inner
Blue ->active
The most inner div with the mouse should have the blue background only.
It works only for very few interactions and most of the times it fails. What would be the best and less resource heavy solution for this problem?
function markActive($el) {
$el.addClass('active');
$el.parent().triggerHandler('inactive');
}
function markInActive($el) {
$el.removeClass('active');
$el.parent().triggerHandler('active');
}
$('div').on({
mouseenter: function() {
markActive($(this));
},
mouseleave: function() {
markInActive($(this));
},
inactive: function() {
markInActive($(this));
},
active: function() {
markActive($(this));
}
});
div {
clear: left;
float: left;
padding-left:20px;
height: 400px;
background: #f00;
}
div div {
height: 125px;
background: #0f0;
}
div div div {
width: 280px;
height: 50px;
background: #ff0;
}
div.active {
background: #00f;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
<div class="outer">
<div class="inner">
<span>Most inner #1</span>
</div>
<div class="inner">
<span>Most inner #2</span>
</div>
</div>
<div class="outer">
<div class="inner">
<span>Most inner #3</span>
</div>
</div>
</div>

Usually what we do need is mouseenter and mouseleave events, those aren't fired when user enters (ou leaves) a child element. In your case you need the old mouseout and mouseover events, that are trigged in that cases.
In the comments you've post a working fiddle: https://jsfiddle.net/ddsxxeer/1/
:)

Related

Toggle only one div element at same position (hide all other div)

I’m new to jQuery and struggling with the .toggle() function.
I want to display several <div>-elements in the same position…but only one at the time. If one <div> is opened and a different one is “toggled” it should automatically be closed.
HTML:
$(document).ready(function() {
$("#button1").click(function() {
$("#box1").toggle(1000);
});
});
$(document).ready(function() {
$("#button2").click(function() {
$("#box2").toggle(1000);
});
});
.container {
width: 90px;
}
.box1 {
background-color: green;
color: red;
display: none;
}
.box2 {
background-color: blue;
color: yellow;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class=box1 id=box1>
This is Box 1
</div>
<div class=box2 id=box2>
This is Box 2
</div>
</div>
Box1
Box2
Also, I am pretty sure that I only need one toggle() function and not 4 for the task I am trying to achieve…but trying to call on the same one does not seem to work with my different id/class.
What am I doing wrong/missing here?
Generally, you can use a single document ready function.
In this case, you could also use a single click function to handle your toggles. Since you're using trigger links, you'll need a way to reference the target box, but something like this would work with an additional attribute to get the box name. (You could do it with indexes as well, but for ease of use, I've added a target-box attribute that has the ID of the desired box.)
I've also added the same box class to both divs, you could remove the individual box1/box2 classes since you have IDs that handle differences already.
I've also added a toggle class to the links to give them a more semantic selector and removed the unnecessary 'open/close' duplicates (since toggle is designed to handle both)
jQuery(document).ready(function($){
$('.toggle').on('click', function(){
var targetBox = $(this).attr('target-box'); // Find the target box
$('.box').not(targetBox).hide(1000); // Hide all other boxes
$(targetBox).toggle(1000); // Toggle the current state of this one
});
});
.container {
width: 90px;
}
.box1 {
background-color: green;
color: red;
display: none;
}
.box2 {
background-color: blue;
color: yellow;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="box box1" id="box1">
This is Box 1
</div>
<div class="box box2" id="box2">
This is Box 2
</div>
</div>
Toggle Box1
Toggle Box2
Something like this may do the trick for you. You can hide all elements marked in some way, e.g. all elements of a class. In this snippet I added the class "box" to all boxes, and on open, I first hide all boxes in this way, before showing the specified box.
Now clicking open will open the specified box and close any others, and clicking close will close the specified box.
$(document).ready(function() {
$("#button1").click(function() {
$(".box").hide(1000);
$("#box1").show(1000);
});
$("#buttonclose").click(function() {
$("#box1").hide(1000);
});
$("#button2").click(function() {
$(".box").hide(1000);
$("#box2").show(1000);
});
$("#buttonclose2").click(function() {
$("#box2").hide(1000);
});
});
.container {
width: 90px;
}
.box1 {
background-color: green;
color: red;
display: none;
}
.box2 {
background-color: blue;
color: yellow;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="box box1" id=box1>
This is Box 1
</div>
<div class="box box2" id=box2>
This is Box 2
</div>
</div>
Close Box1
Close Box2
Open Box1
Open Box2

Targetting specific jquery element which have identical class names

I have several divs which are generating dynamically which share same class names, If I hover on parent(myDiv) need to trigger an event and on hover need to add a class to myDiv(child button) and once I clicked on parent div(myDiv) need to unbind hover action?
<div class="myDiv">
<div class="myBtn"></div>
</div>
<div class="myDiv">
<div class="myBtn"></div>
</div>
<div class="myDiv">
<div class="myBtn"></div>
</div>
Tried in the below way
$(document).on('click', '.myDiv', function() {
//some task will goes here
$(this).unbind('hover');
}).hover(function() {
$(this).find('.myBtn').css('background','#666666');
});
I believe what you are looking for is the .off() function.
Here is the jsFiddle link.
JavaScript:
$(document).on('click', '.myDiv', function() {
//some task will goes here
$(this).off();
});
$('.myDiv').hover(function() {
$(this).find('.myBtn').toggleClass('active');
});
CSS:
.myDiv {
display: block;
height: 100px;
width: 100px;
background-color: red;
}
.myBtn {
display: block;
height: 50px;
width: 100px;
background-color: white;
}
.active {
background-color: gray;
}
I hope this helps.

Issue when animating on hover effects with callbacks

So I am having this issue when I am using the hover event in jQuery. I have two containers side by side. I have hover events on both of them. When hover, a div with additional info slides up into frame. When you hover off, it slides back down.
Simple right? When you hover on an element it should remove the "hide-me" class and start sliding the info up (animating). When you hover off of an element the "hide-me" class should be removed once the animation is complete.This works fine when you hover on and hover off onto an element that is not a grid-item. When you hover off of an item onto another grid-item it seems to just add the class "hide-me" to the currently hovered element. Even though the hover off event hasn't fired yet.
Anyways enough talk here is the code on JS Fiddle:
https://jsfiddle.net/joemoe_1984/2k22yLmd/2/
For testing here is what works:
Hover from below/above image then hover out from below/above image
For testing how it doesn't work:
Hover from below/above image then hover out onto other image
UPDATE
Just to clarify a bit as I had an answer that got me the effect I wanted but didn't exactly solve the issue I was having exactly. I would like to know why the animation callbacks on complete don't properly work when hovering from one image to the other. This is the part that has been bugging me the most. When you hover on an image and then out it removes the class on hover then adds the class after the animation called from the hover out event finishes. This is the expected behaviour. When I hover over an image then onto the other image you will see that instead of adding the class to the first image on hover out, it adds it to the image you are current hovering. Its as if the animation callback is calling the wrong callback function once it animates up on hover.
The on hover state should never have the class added. It should be removed at this point. The class should also not be added during any of the animation states.
Just in case links aren't ok, here is the full html, css and javascript:
HTML
<div class="grid-container">
<div class="grid-item">
<a href="#" class="grid-inner">
<div class="grid-image">
<img src="http://vignette3.wikia.nocookie.net/metroid/images/8/86/Samus_artwork_11.jpg/revision/latest?cb=20100516174330" alt="">
</div>
<div class="grid-info hide-me">
<div class="middle-align">
<h4 class="grid-title">Some title</h4>
<div class="grid-details">
This is some info about this item
</div>
</div>
</div>
</a>
</div>
<div class="grid-item">
<a href="#" class="grid-inner">
<div class="grid-image">
<img src="http://vignette3.wikia.nocookie.net/metroid/images/8/86/Samus_artwork_11.jpg/revision/latest?cb=20100516174330" alt="">
</div>
<div class="grid-info hide-me">
<div class="middle-align">
<h4 class="grid-title">Some title</h4>
<div class="grid-details">
This is some info about this item
</div>
</div>
</div>
</a>
</div>
</div>
CSS
.grid-item {
width: 25%;
float: left;
overflow: hidden;
}
.grid-item img {
max-width: 100%;
height: auto;
}
.grid-inner {
position: relative;
display: block;
}
.grid-info {
position: absolute;
background: blue;
color: white;
width: 100%;
height: 100%;
}
.hide-me {
display: none;
}
.middle-align {
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
Javascript
$(document).ready(function() {
$('.grid-item').hover(hover_in, hover_out);
function hover_in(e) {
$info = $(e.currentTarget).find('.grid-info');
target_height = $(e.currentTarget).height();
$info.css('top', target_height).removeClass('hide-me');
$info.stop().animate({
'top': 0,
}, 500, function() {
console.log('animated up');
});
}
function hover_out(e) {
$info = $(e.currentTarget).find('.grid-info');
target_height = $(e.currentTarget).height();
$info.stop().animate({
'top': target_height,
}, 500, function() {
console.log('animated down');
$info.addClass('hide-me');
});
}
});
Try substituting using .show() after call to .stop() for .removeClass('hide-me') at hover_in
$(document).ready(function() {
$('.grid-item').hover(hover_in, hover_out);
function hover_in(e) {
$info = $(e.currentTarget).find('.grid-info');
target_height = $(e.currentTarget).height();
$info.css('top', target_height) //.removeClass('hide-me')
.stop()
.show()
.animate({
'top': 0,
}, 500, function() {
console.log('animated up');
});
}
function hover_out(e) {
$info = $(e.currentTarget).find('.grid-info');
target_height = $(e.currentTarget).height();
$info.stop().animate({
'top': target_height,
}, 500, function() {
console.log('animated down');
$info.addClass('hide-me');
});
}
});
.grid-item {
width: 25%;
float: left;
overflow: hidden;
}
.grid-item img {
max-width: 100%;
height: auto;
}
.grid-inner {
position: relative;
display: block;
}
.grid-info {
position: absolute;
background: blue;
color: white;
width: 100%;
height: 100%;
}
.hide-me {
display: none;
}
.middle-align {
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<body>
<h1>Animation grid</h1>
<div class="grid-container">
<div class="grid-item">
<a href="#" class="grid-inner">
<div class="grid-image">
<img src="http://vignette3.wikia.nocookie.net/metroid/images/8/86/Samus_artwork_11.jpg/revision/latest?cb=20100516174330" alt="">
</div>
<div class="grid-info hide-me">
<div class="middle-align">
<h4 class="grid-title">Some title</h4>
<div class="grid-details">
This is some info about this item
</div>
</div>
</div>
</a>
</div>
<div class="grid-item">
<a href="#" class="grid-inner">
<div class="grid-image">
<img src="http://vignette3.wikia.nocookie.net/metroid/images/8/86/Samus_artwork_11.jpg/revision/latest?cb=20100516174330" alt="">
</div>
<div class="grid-info hide-me">
<div class="middle-align">
<h4 class="grid-title">Some title</h4>
<div class="grid-details">
This is some info about this item
</div>
</div>
</div>
</a>
</div>
</div>
</body>
jsfiddle https://jsfiddle.net/2k22yLmd/3/
Ok. So I figured it out. It turned out to be a scope issue. The problem stemmed from using e.currentTarget (or this) within the hover event scope. I stored that instance into a variable and then later used it in the callback of the animation sequence.
It appears that the current target changes from when the animation callback uses it giving me the unexpected results. For the animation callbacks I should have used the instance (this) within the scope of the animation callback function like so:
$info.stop().animate({
'top': target_height,
}, 500, function() {
console.log('animated down');
$(this).addClass('hide-me'); // this refers to the current animated object. This is the correct one.
$info.addClass('wrong-one'); // $info refers to the current hover event target which is the on hover item when it should be the hover off item. This is incorrect
});
You can test it out and see that going from one image to the next will now add the class hide-me to the correct one and add the class wrong-one to the currently hovered item which is not the expected behaviour I was looking for.
Thanks to everyone for pitching in on the answers and providing alternative solutions but this was real issue for me.

jQuery draggable position unchanged

I have four draggables next to each other and I want it to be so that once a draggable is remove from the list, the rest would stay in place.
<div class="draggables">
<div id="d1" class="box">
first box</div>
<div id="d2" class="box">
second box</div>
<div id="d3" class="box">
third box</div>
<div id="d4" class="box">
forth box</div>
</div>
CSS
.draggables{
width: inherit;
height: 60px;
margin-left: 20px;
}
.box{
width: 180px;
height: 30px;
float:left;
margin-left: 20px;
}
jQuery:
$("#d1, #d2, #d3, #d4").draggable({
revert: function (event, ui) {
$(this).data("uiDraggable").originalPosition = {
top : 0,
left : 0,
};
return !event;
}
});
You could set the opacity of the "removed" item to 0 to simulate hiding.
Instead of using the revert option, you can use stop to trigger an action when the mouse is released. Also, you don't need to invoke draggable using each individual id. You can simply call it on .box since all of the divs share that class.
In the example below, I'm assigning a class of hidden, which sets the opacity of the chosen div/element to 0.
JQuery:
$(".box").draggable({
stop: function(event, ui) {
$(this).addClass('hidden');
}
});
CSS:
.hidden {
opacity: 0;
}
Fiddle Example

jQuery drag and drop colour div to change background of another

I have the following HTML, containing 4 <div>'s - 2 are doors and 2 are colors, as you can guess from their id.
I'd like to be able to drag either colour to either door (such as blue on the left door and black on the right) and change the background colour on the style.
<div id="door1" style="background: #fff;"></div>
<div id="door2" style="background: #fff;"></div>
<div id="black"></div>
<div id="blue"></div>
I'd be grateful even if someone could point me in the right direction at least.
You should initialize your color <div>'s as draggable and door <div>'s as droppable widgets using .draggable() and .droppable() methods respectively.
Then you can use the drop event handler of droppable for changing the background color. Inside the handler, you can access the droppable using this and dragged element using ui.draggable as shown below:
$(".color").draggable({
revert:true
});
$(".door").droppable({
drop: function(e, ui) {
console.log(ui.draggable)
$(this).css("background-color", ui.draggable.attr("id"));
}
});
.door {
display: inline-block;
width: 50px;
height: 120px;
border: 1px solid;
margin: 5px;
}
.color {
float: right;
width: 50px;
height: 50px;
}
.white {
background: #fff;
}
#black {
background: #000;
}
#blue {
clear: left;
background: royalblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
<div id="door1" class="door white"></div>
<div id="door2" class="door white"></div>
<div id="black" class="color"></div>
<div id="blue" class="color"></div>
Side note: I've removed the inline css and is using css classes, So that you can avoid duplication of styles and keep your HTML clean. You can read more about Why Use CSS # MDN
On the stop event of "draggable" check which div was the target (getting 'left' and 'top' attributes of the div that was dragged) and paint it with the color from the div that was dragged.

Categories