Mouseover/mouseout, mouseenter/mouseleave, hover flickering issue - javascript

I have a div with an image inside it. When I hover the image, I create a tooltip div thats absolutely positioned over part of the image (the absolute position is important). It contains the title and alt text.
This is all well and good until you hover the tooltip box. It doesn't bubble down and it thinks I'm no longer hovering over the image, thus making the tooltip box disapear. But then it registers I'm hovering the image again and it goes back and forth between showing the tooltip box and hiding it.
Thus the flickering issue.
There are a bunch of posts on SO about the flickering issue and I've tried so many solutions but none have been working. I've tried Mouseover/mouseout, mouseenter/mouseleave, hover, and even using live() in combination with them. I even switched from creating the tooltip from scratch to having the empty div there so it would be in the DOM when the page loaded in case that was the issue. I really don't know what to do anymore. Here is my code at the moment.
$("img").bind("mouseover", function() {
var pimg = $(this);
var position = pimg.position();
var top = position.top;
var left = position.left;
var title = $(this).attr('title');
var alt = $(this).attr('alt');
$('.toolTip').css({'left' : left, 'top' : top, 'width' : width}).append('<div><h3>' + title + '</h3><p>' + alt + '</p></div>');
});
$("img").bind("mouseout", function() {
$('.toolTip').empty();
});

The problem is a) you need to use mouseenter / mouseleave and b) the tooltip div needs to live inside the element that has the mouseenter / mouseleave listeners.
eg:
<div id="mouseoverdiv">
<div class="tooltip">some text</div>
<img src="" />
</div>

Related

Stuttering on mouseout of moved image element

Basically, when hovering over an image, I'd like to move the image slightly and then on mouseout, return the image to the original location. I've got a version of the code that works to accomplish this task but there is a bit of a "stuttering" effect if the user was to move the mouse from the image into the area where the image was located originally.
-----
| |
----- |img|
| | | |
|img| ==> -----
| | xxxxx
----- xxxxx
In the diagram above, when the mouse hovers over the image, it gets nudged up 2 units. On mouseout, the image returns to the original position. My code, as below, works but when the mouse gets moved into the previously vacated area (e.g., the x's), the code thinks that it's hovering over the image again and then moves the image back up 2 units. This creates a sort of stuttering effect when hovering the mouse over the area marked by x above.
I've tried different approaches (e.g., using animate(), adding/removing a wrapper div, using setTimeout(), etc) but they all produce the same undesired effect. I considered constantly monitoring the mouse position on the page and remembering the position of the image, but that seems excessive, esp since there could be anywhere between 1 and n images.
$(document).ready(function() {
$('.hoverImage').hover(
function(){
$(this).offset({'top':$(this).offset().top-2});
},
function(){
$(this).offset({'top':$(this).offset().top+2});
}
);
});
Here is a jsfiddle demo-ing the issue: http://jsfiddle.net/Ut8eK/
Any tips would be much appreciated. Thanks in advance!
Update
Awesome. I ended up using a bit of both answers:
$(document).ready(function() {
$('.hoverImage').wrap('<div class="hoverImageWrapper" style="display: inline-block;">');
$('.hoverImageWrapper').hover(
function(){
$('.hoverImage',this).offset({'top':$(this).offset().top-10});
},
function(){
$('.hoverImage',this).offset({'top':$(this).offset().top});
}
);
});
Here's a jsfiddle of the above: http://jsfiddle.net/rf5mE/
This works great for my needs, since adding the functionality will be super easy just by adding class="hoverImage" to the appropriate images.
I accepted #Matyas as the answer only because his answer came through first (by about 4 seconds!).
Thanks y'all!
You should put your images in a wrapper, and listen to the hover in the wrapper, which doesn't change its position. This way you should get a constant effect
EDIT:
The problem is that the image moves lower on mouseout than the size of the div (original size of the image) Solution: add a 10px bottom padding to the div, in the case the image moves 10px lower, to still have a div in its background if it's hovered. (updated link)
TY Huangism for the notification
Update example:
HTML
<br />
<div>< img src="http://placekitten.com/120/100" class="hoverImage" /></div>
<div>< img src="http://placekitten.com/100/100" class="hoverImage" /></div>
<div>< img src="http://placekitten.com/110/100" class="hoverImage" /></div>
JS
$(document).ready(function() {
$('div').hover(
function(){
//search for the image inside the wrapper (reffered to by this)
$('.hoverImage', this).offset({'top':$(this).offset().top-10});
},
function(){
$('.hoverImage', this).offset({'top':$(this).offset().top+10});
}
);
});
CSS:
div{
display: inline-block;
}
div:hover{
padding-bottom: 10px;
}
Put a wrapper on it and target the wrapper to move the image
http://jsfiddle.net/Ut8eK/4/
HTML
<div class="hoverImage"><img src="http://placekitten.com/120/100" /></div>
JS
$(document).ready(function() {
$('.hoverImage').hover(
function(){
var $img = $(this).find('img');
$img.offset({'top':$img.offset().top-10});
},
function(){
var $img = $(this).find('img');
$img.offset({'top':$img.offset().top+10});
}
);
});
for multiple divs you do need the inline-block css

Image Map with Image popup on hover over hotspot

I am building a calendar that has events on certain days. The calendar is a jpg that I have created an image map for. When you hover over a hotspot or "event" on the calendar, I want an image to hover next to the mouse pointer that will have the event information on it, and then disappear when the mouse goes off of the hotspot. I have six hotspots, and a javascript function for each. The functions replace the popup image with the correct event image. Below is an example of just one of the areas along with one function (the others are identical w/ different image names and coords)
I had the event images popping up below the calendar on hover but the page refused to relocate the position of the image to the current mouse location. How can I make the popup image relocate? What am I doing wrong? or should I be using a different method?
JS:
function pop(e) { //function called by first hotspot
Image.src = "../img/Bubble - Aloha.png" //event image
document.popup1.src = Image.src;
var thing = document.getElementById("popup1");
$("#popup1").toggle();
thing.style.left = e.screenX + 'px';
thing.style.top = e.screenY + 'px';
return true;
}
MAP:
<map id="feb1050" name="feb1050">
<area shape="rect" alt="" coords="464,170,588,263" HREF="../img/feb1050.jpg" onMouseOver="pop(event);" onMouseOut="pop(event);"/>
...</map>
HTML:
<ul><li>
<img src="../img/feb1050.jpg" width="1050" alt="calendar" USEMAP="#feb1050">
</li>
<li>
<div id="popup"><img NAME="popup1" id="popup1" src="../img/Bubble - Aloha.png" width="400" alt="calendar" style="display:none;top:-2000;left:-1000;>
</div><br />Click Here To RSVP!
</li>
</ul>
Perhaps rather than manipulating the position of the image itself, you could position the enclosing div. For the HTML:
<div id="popup" class="popup"><img NAME="popup1" id="popup1" src="../img/feb1050.jpg" alt="calendar">
<br />Click Here To RSVP!</div>
With some CSS for the div:
.popup {
position:absolute;
z-index:20000;
top: 0px;
left: 0px;
display: none;
}
And then the JS:
function pop(e) { //function called by first hotspot
Image.src = "../img/Bubble - Aloha.png" //event image
document.popup1.src = Image.src;
var thing = document.getElementById("popup");
thing.style.left = e.clientX + 'px';
thing.style.top = e.clientY + 'px';
$("#popup").toggle();
return true;
}
Note that I would also use clientX and clientY rather than screenX and screenY:
What is the difference between screenX/Y, clientX/Y and pageX/Y?
Working example on JSFiddle
One thing I have done (in a situation almost exactly like this: A client wanted some pricing boxes to appear when hovering over a price keyword) is almost purely CSS and HTML. You can generate the popup areas inside <a> tags, which are then placed inside some <span> (or absolutely-positioned <div>) placed next to the hover area. You make sure those span/div elements are only defined for the a:hover selector, and you set them to display:none; on the rest of the a:x selectors, so that the span/div box only appears when you are hovering over the anchor, and disappears when you are not.

How to resolve mouse hover on overlapping images in jQuery?

This question seems somewhat related to
How do I check if the mouse is over an element in jQuery?
jQuery check hover status before start trigger
but still not quite. Here's the thing: I'm writing a small gallery and at some point the user clicks on a thumbnail. The large version of the image shows as an inside of a full-screen . So far, so good. When the mouse hovers over that I show three images: close, left, right, intended to navigate through an album; when the mouse leaves the image or the navigation images, the three navigation images fade.
These three navigation images partially overlap with the main image, e.g. the close image is a circle in the upper left corner. And that's the tricky part.
The mouseleave triggers whenever the mouse moves from the main image off the side, or from the main image onto one of the three small overlapping images. The mouseenter triggers for each of the small overlapping images as expected.
However, this creates a funky blinking effect because on mouseleave of the main image I hide() the three small images, which immediately triggers a mouseenter for the main image because of the overlap and the mouse still being on top of the main image.
To avoid that, I tried to determine if, upon mouseleave of the main image, the mouse has moved onto one of the small overlapping images. For that, I used this code:
main_img.mouseleave(function() {
if (!hoverButtons()) {
doHideButtons();
}
});
function hoverButtons() {
return (close_img.is(":hover")) || (left_img.is(":hover")) || (right_img.is(":hover"));
}
This works great on Safari and Chrome, but not on FF and IE where the images still blink. Further noodling around posts, it seems that ":hover" is the problem here as it is not a proper selector expression but rather a CSS pseudo class?
I tried to work with switches that I flip on/off as I mouseenter/mouseleave the various images, but that doesn't work either because the events seem to trigger in different orders.
How do I go about this? Thanks!
EDIT: I might have to clarify: before the navigation buttons are shown, I set their respective left and top attributes in order to place them in dependence of the main image's position. That means I need to do some work before I can call .show() on a jQuery selector. I tried to add a new function .placeShow() but that didn't quite work with respect to selectors like $(".nav-button:hidden").placeShow().
You can try with this:
$("#main, #small").mouseenter(function() {
$("#small:hidden").show();
}).mouseleave(function(e) {
if(e.target.id != 'main' || e.target.id != 'small') {
$('#small').hide();
}
});
DEMO
Here is what I ended up doing. There are four images I use in my slide show: the main image, and then left, right, close button images.
main_img = $("<img ... class='main-photo slide-show'/>");
close_img = $("<img ... class='nav-button slide-show'/>");
left_img = $("<img ... class='nav-button slide-show'/>");
right_img = $("<img ... class='nav-button slide-show'/>");
The classes here are essentially empty, but help me to select based on above answers. The main image then shows without navigation buttons, and I attach these event handler functions:
$(".slide-show").mouseenter(function() {
$(".photo-nav:hidden").placeShow();
});
$(".slide-show").mouseleave(function() {
$(".photo-nav").hide();
});
where the placeShow() moves the navigation buttons into their respective places. This function is defined as follows:
$.fn.placeShow = function() {
var pos = main_img.position();
var left = pos.left;
var top = pos.top;
var width = main_img.width();
var height = main_img.height();
close_img.css({ "left":"" + (left-15) + "px", "top":"" + (top-15) + "px" }).show();
left_img.css({ "left":"" + (left+(width/2)-36) + "px" , "top": "" + (top+height-15) + "px" }).show();
right_img.css({ "left":"" + (left+(width/2)+3) + "px", "top":"" + (top+height-15) + "px" }).show();
}
This worked so far on Safari, IE, FF, Chrome (well, the versions I've got here...)
Let me know what you think, if I can trim this code more, or if there are alternative solutions that would be more elegant/fast. The final result of all this is on my website now.
Jens

Google plus popup box when hovering over thumbnail?

I'm trying to figure out how to create a popup box with user profile details on mouseover like you see on google plus. When hovering over a thumbnail a popup appears with the option to add that person into your circle.
It seems kinda simple to do with jQuery but I've been unable to find a simple solution. Most of the plugins I've come across are too complicated and require a lot of tweaking. Any help on how to do this would be greatly appreciated!
Hover Effect Screenshot
You'll want to try something like this. It doesn't handle all the cases you'll need (you need the hover to stay active when user enters the popup); but you can work some of those out I hope.
Here's the basic jQuery code:
jQuery(function($) {
function getMyContent($img) {
// do your fancy ajax calls or append your control links and such here
return $('<p />').append($img.clone()).append('Here is my fancy hoverbox');
}
$('#content img').mouseenter(function(e) {
var $this = $(this), off = $this.offset();
var pos = {
// or you could position it relative to the mouse
top: (e.clientY + 2) + 'px',
left: (e.clientX + 2) + 'px'
};
$('#hoverbox').css(pos)
.append(getMyContent($this))
.fadeTo('slow', .95);
}).mouseleave(function(e) {
$('#hoverbox').fadeOut('slow', function() { $(this).html(''); });
});
});
UPDATE: Here is one that handles the hover events on the popup for you (yeah, I'm still messing around with it; why?)
The simplest solution would be to add a hidden div to the element that wraps around your profile photo.
<div class="profile-popup" style="display: none;">
<!-- Popup info goes here -->
</div>
Go ahead and style the div with CSS however you want it to appear, say with absolute positioning at the bottom right corner for the "pop out" effect. Then register a mouseOver event in jQuery that shows the div:
$().ready( function() {
$('.profile-pic-wrapper').mouseenter( function() {
$('.profile-popup', this).show( //pass in some animation options here );
});
$('.profile-pic-wrapper').mouseleave( function() {
$('.profile-popup', this).hide( //pass in some animation options here );
});
});
This is just a basic idea (and that code may need to be tweaked a bit). You'll have to add some additional logic to keep the popup open when the user mouses into it, but this should get you started.
The more elegant solution would be to pass JSON data to your jQuery script and have it generate the popup div dynamically on hover, but that is a bit more advanced.

How can I work around reloading these images?

I have a simple jQuery image changer, that when you hover over it will make swap all images with their grey version except the one you are on, that one will stay colour (They are all colour to begin with) and when you hover over another image, the last image gets changed to grey and the new one gets changed to colour.
However on IE, when you hover through the images, because it is changing the src IE will display the coloured version for a split second before doing what it is supposed to.
Here is the code:
$(window).load(function() {
//when mouse over the list item...
$('#portfolio ul li').hover(function(){
$(this).find('img').addClass('active');
$(this).siblings().each(function(Idx){
var imgSrc = ""+$(this).find('img').attr('src');
var imgGS = ""+$(this).find('a').attr('rel');
$(this).find('img').attr('src', imgGS);
$(this).find('a').attr('rel', imgSrc);
//alert (imgSrc + " " + imgGS);
});
//when mouse leave...
}, function(){
$(this).find('img').removeClass('active');
$(this).siblings().each(function(Idx){
var imgGS = $(this).find('img').attr('src');
var imgSrc = $(this).find('a').attr('rel');
$(this).find('a').attr('rel',imgGS);
$(this).find('img').attr('src', imgSrc);
//alert (imgSrc + " " + imgGS);
});
});
//when mouse leaves the unordered list...
$('#portfolio ul').bind('mouseleave',function(){
$(this).siblings().each(function(Idx){
var imgSrc = $(this).find('img').attr('src');
var imgGS = $(this).find('a').attr('rel');
$(this).find('img').attr('src', imgSrc);
$(this).find('a').attr('rel',imgGS);
// alert (imgSrc + " " + imgGS);
});
});
});
Any help would be appreciated :)
Thanks.
Try using image sprites for this. This involves putting both grey and colour in the same image and then instead of changing the source you simply change which part of the image gets shown. The solves the problem of your browser having to load images on the fly as they will already be loaded.
You could display the color image as a regular <img> and then the gray version is the css background. On hover, fade it's siblings img's out.
Something like
​$('.yourList li').hover(function() {
$(this).siblings().find('img').hide();
},function() {
$(this).siblings().find('img').show();
});​​​​​​​​​​​​​​​
Just make sure you either have content keeping that li from collapsing, or you manually set the dimensions.
Pixastic for catering to standards compliant browsers and css filters for IE should do the trick. dont need multiple images
http://www.pixastic.com/lib/download/

Categories

Resources