Overlay div onto td cell using jquery.position upon mouseover event - javascript

I have a large table with numbers only and a small font-size, which makes it hard to see. Increasing font-size is not a option, but I want to supply a zoom like effect (without having to use browser zoom) using a simple div overlay upon hovered td cell if it has any content.
The div should be centered on the td cell and the content of the div should be replaced the text content of hovered td cell.
Where is my error ?
Note: I am using .delegate() instead of .hover() because I already am doing other stuff which require delegate.
HTML
<div id="mine"><table border="1" cellspacing="2" cellpadding="2">
<tr><td></td><td></td><td>1</td><td>2</td></tr>
<tr><td>3</td><td></td><td></td><td>5</td></tr>
</table></div>
<div id="your">vale</div>
CSS
#your {
position: absolute;
width: 40px;
height: 30px;
z-index: 100;
border: 1px solid green;
text-align: center;
vertical-align: middle;
}
JS
$(document).ready(function() {
$('#mine').delegate('td', 'mouseover mouseleave', function(e) {
if ($(this).text().length > 0) {
if (e.type == 'mouseover') {
$('#your').position({
my: "center bottom",
at: "center top",
of: this,
offset: "0 -20", // Place it above td cell
collision: "none"
});
$('#your').clearQueue();
$('#your').text($(this).text()).fadeIn(200);
} else {
$('#your').delay(300).fadeOut(200);
}
}
});
});
Edit I am seeing #your flying all over the place at first run, then the next few hovers it works, but then it begins to pop up all weird places - including outside #mine.

If your problem is the flicker that happens, it's because you have it fading out #your when you leave the td, which you leave the second #your appears (because #your appears under your mouse cursor at that time since you are hovering directly over the td)
Way to fix this is to remove the mouseleave from #mine and create a separate listener for mouseleave specifically for #your. So when your mouse leaves #your it will fadeOut #your.
$(document).ready(function() {
$('#mine').delegate('td', 'mouseover', function(e) {
if ($(this).text().length > 0) {
if (e.type == 'mouseover') {
$('#your').position({
my: "center",
at: "center",
of: e,
collision: "none"
});
$('#your').clearQueue();
$('#your').text($(this).text()).fadeIn(200);
}
}
});
});
$('#your').mouseleave(function() {
$(this).fadeOut(200)
});
Also, alter your CSS so that #your doesn't start out visible.
#your {
position: absolute;
display: none;
width: 40px;
height: 30px;
z-index: 100;
border: 1px solid green;
text-align: center;
vertical-align: middle;
}

Using an overlay div, which is larger than the element it overlays was a bad idea - it had to be somewhere else.
Here is what I ended up doing as splitting up "mouseover" & "mouseleave" was NOT an option, due to other things preformed.
JS
$(document).ready(function() {
$('#mine').delegate('td', 'mouseover mouseleave', function(e) {
if ($(this).text().length > 0) {
if (e.type == 'mouseover') {
var off = $(this).offset();
$('#your').css({ // Using .position() was buggy. Styles ALWAYS works
opacity: '', // Remove it if fadeOut didnt finish properly, eg too fast mouse movement
left: (off.left -14)+'px', // 14 is half of box width
top: (off.top -20 -37)+'px', // 37 is height of font within box. 20 is to place it above
});
$('#your').clearQueue().text($(this).text()).show(); // fadeIn wasnt really needed
} else {
$('#your').delay(900).fadeOut(150); // long delay to allow moving mouse to another cell without box disappearing fast, else fade out fast
}
}
});
});

Related

jQuery fixed navbar that shrinks to a smaller size on scroll is being super buggy

When using a combination of jQuery and CSS to trigger my navbar to shrink on scroll, it get's buggy when you scroll back up to a certain position, I have linked a video as an example.
I have tried two different methods. The first is using $(window).scrollTop) with an if statement and a series of .addClass and .removeClass. The second thing I have tried is using $(window).scrollTop) with a series of .css dynamic style modifications. Both of these attempts render the same end result that is shown in this video https://youtu.be/YXKsrL1cghs .
My first jQuery attempt:
$(document).ready(function () {
$(window).on("scroll", function () {
if ($(window).scrollTop() >= 40) {
$(".navbar").removeClass("py-5");
$(".navbar").addClass("compressed");
} else {
$(".navbar").addClass("py-5");
$(".navbar").removeClass("compressed");
}
});
});
My second jQuery attempt:
$(document).ready(function () {
$(window).on("scroll", function () {
if ($(window).scrollTop() >= 40) {
$(".navbar").css({ "padding-top": "10px" });
$(".navbar").css({ "padding-bottom": "10px" });
} else {
$(".navbar").css({ "padding-top": "3rem" });
$(".navbar").css({ "padding-bottom": "3rem" });
}
});
});
My CSS:
.navbar.compressed {
padding-top: 10px;
padding-bottom: 10px;
}
My expected results would be a smooth scrolling fixed navbar that shrinks to a smaller size after scrolling beyond a certain point.
What actually occurs is that when you scroll down past a certain point, for 20px worth of height, it gets super buggy and starts bouncing up and down. Once you clear those 20 or so px it's perfectly fine, but when you scroll back up it acts the same within those 20px.
When watching the video, I noticed that your .navbar has transition: all .3s. It could be the reason that when you remove the class py-5 and add class compressed, it triggers the transition twice.
It would be helpful if you can provide the HTML markup and CSS as well.
The script is manipulating the DOM quite a lot. I am not sure if this is going to fix your problem but it might be a good idea to only change the classes if the have not yet been applied.
$(document).ready(function() {
$(window).on("scroll", function() {
let navbar = $(".navbar");
if ($(window).scrollTop() >= 40) {
if (navbar.hasClass("py-5")) {
navbar.removeClass("py-5");
navbar.addClass("compressed");
}
} else {
if (navbar.hasClass("compressed")) {
navbar.addClass("py-5");
navbar.removeClass("compressed");
}
}
});
});
body {
height: 10000px;
position: relative;
}
.navbar {
width: 100%;
position: fixed;
height: 50px;
top: 0;
transition: all .3s
}
.py-5 {
background-color: blue;
padding-top: 10px;
padding-bottom: 10px;
}
.compressed {
background-color: red;
padding-top: 0px;
padding-bottom: 0px;
}
<html>
<head></head>
<body>
<nav class="navbar py-5">Navigation</nav>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</body>
</html>

How to fade in and out a tag when entering a control in a set from outside of it?

I have a bunch of colored areas and when I enter any of them, I want the text to fade out. When I'm leaving the colored area, I want the text to fade in. This far, it's easy. The problem arises when I leave an area and enter an adjacent one.
If I only toggleIn() and toggleOut(), it works, but the fading effect makes the text appear and then re-disappear again, which looks stupid.
The extra problem is that the areas can't be placed in a single holder because they are not rectangularly positioned (and, in fact, it's parts of a SVG based pie chart drawn with D3).
I've been testing an external variable to keep track in the entry is made from outside of all areas or from outside of this but inside of another, adjacent area). Didn't quite managed to work it out.
How to make it happen in this fiddle?
$(".dragon")
.on("mouseenter", function(target) {
$("#indicator").fadeOut();
})
.on("mouseleave", function(target) {
$("#indicator").fadeIn();
});
The fadeIn() and fadeOut() functions can take an options parameter. One of the options is queue. If you set that to false on the fadeOut(), then it will interrupt the fade in animation. You won't see the full opacity text when you move between hover targets.
$(".dragon")
.on("mouseenter", function(target) {
$("#indicator").fadeOut({queue: false});
})
.on("mouseleave", function(target) {
$("#indicator").fadeIn();
});
div {
width: 200px;
height: 200px;
text-align: center;
}
.uno {
background-color: blue;
}
.duo {
background-color: yellow;
}
#indicator {
color: red;
font-family: Tahoma;
font-size: 32px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dragon uno"></div>
<div class="dragon duo"></div>
<div id="indicator"><hr>Enter the dragon!</div>
Update
There seems to be an issue with jQuery's fadeIn() and fadeOut() functions where they get confused by mouseenter and mouseleave events that are quick in succession. Switching to using the animate() function directly seems to fix the problem though.
$(".dragon")
.on("mouseenter", function(target) {
$("#indicator").animate({opacity: 0}, {queue: false});
})
.on("mouseleave", function(target) {
$("#indicator").animate({opacity: 1});
});
$(".dragon")
.on("mouseenter", function(target) {
$("#indicator").animate({opacity: 0}, {queue: false});
})
.on("mouseleave", function(target) {
$("#indicator").animate({opacity: 1});
});
div {
width: 200px;
height: 200px;
text-align: center;
}
.uno {
background-color: blue;
}
.duo {
background-color: yellow;
}
#indicator {
color: red;
font-family: Tahoma;
font-size: 32px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dragon uno"></div>
<div class="dragon duo"></div>
<div id="indicator"><hr>Enter the dragon!</div>
When you go from a dragon area to another the first one's mouseleave() event will rise and the second one's mouseenter() event will rise. That's why it shows the text and hide it again. This is what i resolved by updating your jsfiddle.
As I inderstood from your question when the user enters to the ".dragon" area you want to hide the text. And when passing from a ".dragon" element to another instead of just showing and hiding the text you want the text to just stay hidden.
A solution i can think of is in the document ready function you can create two global variables for bottom-right corner of the ".dragon" elements. Let's say the variables are (according to the size of your Jsfiddle);
var globalX = 200;
var globalY = 400;
And you put your fade functionality into mousemove() event.
$('body').mousemove(function(event){
if(event.pageY > 400 || event.pageX > 200){
$("#indicator").fadeIn();
}
else{
$("#indicator").fadeOut();
}
});
What you require is a delay in checking mouse after it leaves an element. See my example using isHover variable with a 300ms delay using setTimeout()
Update: Shorten delay to 50ms, assuming colored areas are side by side.
var isHover = false;
$(".dragon")
.on("mouseenter", function(target) {
isHover = true;
checkHover();
})
.on("mouseleave", function(target) {
isHover = false;
setTimeout(function(){ checkHover(); }, 50);
});
function checkHover() {
if (isHover) {
$('#indicator').fadeOut();
} else {
$('#indicator').fadeIn();
}
}
div {
width: 50px;
height: 50px;
text-align: center;
}
.uno {
background-color: blue;
}
.duo {
background-color: yellow;
}
#indicator {
color: red;
font-family: Tahoma;
font-size: 32px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dragon uno"></div>
<div class="dragon duo"></div>
<div id="indicator"><hr>Enter the dragon!</div>

How to move/position DIV container by changing CSS values using Javascript?

I got two div containers as blocks with some fixed width and maybe height and display: block;
<div class="one"></div>
<div class="two"></div>
When you hover your mouse over container .one I need somehow to apply margin-top (or padding-top) to container .two so it moves couple pixels below while mouse is over .one and when you move mouse pointer aside, .two comes back to it's original position.
.one:hover + .two
{
margin-top: 2px;
}
second div must be followed by first div
.one:hover ~ .two
{
margin-top: 2px;
}
If some other element present between one and two, try this.
For your javascript (jQuery) solution:
$( ".one" ).hover(
function() {
$('.two').css('marginTop', '5px');
}, function() {
$('.two').css('marginTop', '0');
});
For smoother movement:
$( ".one" ).hover(
function() {
$('.two').animate({
marginTop: "5px"
}, 500 );
}, function() {
$('.two').animate({
marginTop: "0"
}, 500 );
});
Added a Demo

javascript window scroll issue

I am working on javascript scroll. I have following html code
JSFIDDLE
<div class="wrapper">
<div class="red div current"></div>
<div class="blue div"></div>
<div class="green div"></div>
<div class="yellow div"></div>
</div>
In above code I have four div tags red, blue, green and yellow. All of them are position in following css.
html, body {
height: 100%;
}
.wrapper {
overflow: hidden;
height: 100%;
}
.div {
position: relative;
height: 100%;
}
.red {
background: red;
}
.blue {
background: blue;
}
.green {
background: green;
}
.yellow {
background: yellow;
}
In above html and css the red div tag is the current one which means user is seeing the red div tag on the screen. Now what I am trying to do is when user scroll over window once, then the next div tag i.e. blue will be animated and moved to the top and will become visible to the user whereas the red div tag will be behind the blue one. This same process goes for both green and yellow.
The problem is that when user scroll once then the div tag should animate however my current javascript code is keep reading the scroll and animating the div tags one after another. What I want is when user scroll once then scroll should be disabled until the blue div tag is animated. Then scroll should be enabled. Again when user scroll second time, the scroll should disable until the green div tag completes its animation. Same goes for yellow.
How can I achieve above?
Here is my javascript
$(window).on("scroll", function () {
var next = $('.current').next();
var height = next.outerHeight();
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().removeClass('current');
$(this).addClass('current');
});
});
Please have a look on update JsFiddle
$(window).on("scroll", function () {
var next = $('.current').next();
var height = $('.current').outerHeight();
$('.current').prevAll().each(function(){
height += $(this).outerHeight();
});
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().css('top','');
$(this).prev().toggleClass('current');
$(this).toggleClass('current');
});
});
The main reason your example wasn't working as expected is because you were relatively positioning the divs, and not moving them to the correct spot.
Working JSFiddle:
http://jsfiddle.net/seanjohnson08/rVVuc/6/
.wrapper {
overflow: hidden;
height: 100%;
position: relative;
}
.div {
position: absolute;
height: 100%;
width: 100%;
top: 100%;
}
.current{
top: 0;
}
If you are looking for a way to limit the amount of scroll events fired, try throttling: http://benalman.com/projects/jquery-throttle-debounce-plugin/. My solution doesn't require this, because no matter how many times it is firing the scroll event, it only ever tells jquery to animate to top:0, there's no chance of it animating past that.

Keep a second div visible if the mouse is over the first or second div

There are two divs; Div A (display:none by default) and Div B (visible all the time). How would one make it so if mouse moves over Div B, Div A becomes visible. Div A should remain visible if the mouse cursor is on either Div A or Div B, otherwise Div A should be hidden.
I'm using jQuery plugin hoverIntent for this.
$(".the-dropdown").hoverIntent( function(){
$(".the-dropdown").show();
}, function(){
$(".the-dropdown").hide();
});
$(".menu-item").hoverIntent( function(){
$(".the-dropdown").show();
}, function(){
$(".the-dropdown").hide();
});
jsfiddle
Hmm, try something like this.
HTML:
<div id="a"></div>
<div id="b"></div>
CSS:
div {
height: 200px;
width: 200px;
}
#a {
background: #0f0;
display: none;
}
#b {
background: #f0f;
}
JS:
$('#a, #b').hover(function() {
$('#a').show();
}, function() {
$('#a').hide();
});
Fiddle
Or in your specific case:
$(".the-dropdown, .menu-item").hover( function(){
$(".the-dropdown").show();
}, function(){
$(".the-dropdown").hide();
});
hoverIntent is a plug-in that attempts to determine the user's
intent... like a crystal ball, only with mouse movement! It is similar
to jQuery's hover method. However, instead of calling the handlerIn
function immediately, hoverIntent waits until the user's mouse slows
down enough before making the call.
Why? To delay or prevent the accidental firing of animations or ajax
calls. Simple timeouts work for small areas, but if your target area
is large it may execute regardless of intent. That's where hoverIntent
comes in...
If you would like to use the hoverIntent plugin you can download it here:
http://cherne.net/brian/resources/jquery.hoverIntent.html
Working Example Using hoverIntent
$(".menu-item").hoverIntent({
over: function () {
$(".the-dropdown").slideDown();
},
out: function () {
$(".the-dropdown").slideUp();
},
timeout: 500,
interval: 500
});
<div class="menu-item">Hover this for half a second
<div class="the-dropdown"></div>
</div>
div {
height: 200px;
width: 200px;
}
.the-dropdown {
background: red;
display: none;
position:relative;
top:182px;
}
.menu-item {
background: blue;
}

Categories