Is it possible to have the zoomed hover image to always show on the screen relative to the cursor but always on the viewable screen? My gallery items come close to the edge of the page, and hovers there always show only partially, leaving the viewer to scroll to the right (or down) to see the whole zoom.

Comments

texas-bronius’s picture

Ok I'm getting somewhere with this feature request.. See attached exemplifying.

Near the top of hover_preview.js just after x and y offsets are defined:

	var hBounds = $(window).width() + $(window).scrollLeft();
	var vBounds = $(window).height();  // this seems somewhat correct?
        ...
	var xPos = (e.pageX + xOffset + hoverWidth < hBounds) ? e.pageX + xOffset : e.pageX + xOffset - hoverWidth;
	var yPos = (e.pageY + yOffset + hoverHeight < vBounds) ? e.pageY + yOffset : e.pageY - yOffset - hoverHeight;
    $("#hover-preview")
      .css("top",(yPos) + "px")
      .css("left",(xPos) + "px");
    ...

I'm still having inconsistency troubles with vertical boundaries.. any ideas here?

rjbrown99’s picture

There is some code in the comment string here:
http://cssglobe.com/post/1695/easiest-tooltip-and-image-preview-using-jq...

Marko Vierimaa specifically has a fix to keep it in the viewport. I have been testing this, and so far it works for images that would otherwise go beyond the bottom of the browser. It does not address the issue where images appear to the right of the cursor and may go offscreen to the right. I was considering this as a partial fix.

Here's the complete js code I have been testing with.

// $Id: hover_preview.js,v 1.1 2010/02/12 00:25:08 rjbrown99 Exp $

/*
 * Hover preview javascript
 *
 * Inspired by http://cssglobe.com/post/1695/easiest-tooltip-and-image-preview-using-jquery
 *   by Alen Grakalic (http://cssglobe.com)
 *
 */

Drupal.behaviors.HoverPreview = function (context) {
  /* CONFIG */
    
    xOffset = 10;
    yOffset = 30;
    
    // these 2 variable determine popup's distance from the cursor
    // you might want to adjust to get the right result
    
  /* END CONFIG */
  $("img.hover-preview").hover(function(e){
    this.t = this.title;
    this.title = "";  
    var c = (this.t != "") ? "<br/>" + this.t : "";
    var preview_link = $('#' + this.id + '-url')[0];
    $("body").append("<p id='hover-preview'><img src='"+ preview_link.href +"' alt='Loading Image Preview' />"+ c +"</p>");                
    $("#hover-preview")
      .css("top",(e.pageY - xOffset) + "px")
      .css("left",(e.pageX + yOffset) + "px")
      .fadeIn("fast");            
    },
  function(){
    if (this.t) {
      this.title = this.t;  
    }
          $("#hover-preview").remove();
    }); 
  $("img.hover-preview").mousemove(function(e){
    var posY;

    if (e.pageY - $(window).scrollTop() + $('#hover-preview').height() >= $(window).height() ) {
      posY = $(window).height() + $(window).scrollTop() - $('#hover-preview').height() - 15 ;
    } else {
      posY = e.pageY - 15;
    }
    $("#hover-preview")
      .css("top",(posY) + "px")
      .css("left",(e.pageX + 15) + "px");
  }); 
};
texas-bronius’s picture

Awesome, looks like we're on the same page.

The problem I am seeing (which is the case in both code snippets, though I've not tried out yours yet) is that the initial placement of the image is not constrained to the display boundaries. So, the first hover of a thumb near a page boundary potentially pops up the image out of bounds, and only on the a mousemove does the proper boundary-check occur.

rjbrown99’s picture

Yep, I'm right with you and I'd also like to fix this. The code snippet I pasted above works to 'move' the image back on screen. If you initially hover, the image might be off screen but any movement of the mouse will bring it back. I haven't taken a look at how to make sure it always moves back into the viewable browser area. If you find the answer in the meantime feel free to post it back.

jon_stewart’s picture

Subscribing: especially with regard to the vertical visibility.

Excellent Module. Well done.

mrfelton’s picture

subscribing

jdfan’s picture

I'm working on a solution to prevent hovered images from being hidden by the bottom border. Here's my rough logic so far:

- preload the hover image
- once it's loaded, get its height
- if the image height + mouse position > viewport bottom, set the top to an appropriate value
- if not, leave the top value alone
- show the image

I'm having a weird caching problem right now but I'm hoping to have it figured out in a few days.

rjbrown99’s picture

jdfan - have a look at the URL I linked to in #2. There's a huge comment string with lots of people who have changed/edited/enhanced the javascript effect. It might be helpful to your efforts.

I also posted the code in #2 which works for me in keeping it from being hidden by the BOTTOM border, but it doesn't work for left/right borers.

I'm happy to review and commit fixes to the module.

mrfelton’s picture

Yeah, I'm also using a slightly modified version of the patch at #2. It does work for the vertical, but not for the horizontal. As a quick fix I just adjusted the offset values to ensure that my hover images display to the left of the mouse, since my images are all on the right hand side of the page.

@jdfn: Your logic sounds reasonable to me. I'm happy to test any patches.

jdfan’s picture

Sorry... went down the wrong rabbit hole.

LightFromArt’s picture

Thank you mrfelton for good news.
Could you put here your version of the code?

rjbrown99’s picture

I'd definitely be interested in enhanced code and patches for this issue. If it seems to work I'm happy to commit it to the next -dev release. jdfan and mrfelton please feel free to drop it into this issue.

jdfan’s picture

Ok, I've found a solution that works for me :) My code is below... sorry it's not a patch.

I've added hoverMultiply, bottomGuard, and topGuard. hoverMultiply is how much larger the hover image is in comparison to the original. In my case, the original is 98px wide and the hovered images are 220px wide, so my multiplier is 2.24 (roughly). bottomGuard and topGuard are 'spacers'. I have a fixed header on my pages, so my topGuard is 60. bottomGuard helps take into account the image title and the overall box for the image.

So, I find out how large the original image is. I went this route because loading the hovered image to find its size turned out to have all sorts of problems.

Based on the original image, I check to make sure the bottom of the hovered image will fall within the window. If not, I adjust the hover top position relative to the window bottom.

Next, I check where the top of the hovered image will land. This accounts for original images where the top is above the viewport (scrollTop). If the hovered image is less than scrollTop, I adjust the hover top. This also accounts for hover images that are larger than the viewport and assumes that seeing the top of the image is more important.

I wanted my hover images to appear offset from my originals and not move as the mouse cursor moves, so I added the hoverX setting and removed the mousemove function.

Edit: Added right/left checking and hover image size checking (and scaling). Works for smaller view ports now and hovered images that are larger than the viewport are scaled down to fit.

Drupal.behaviors.HoverPreview = function (context) {
  /* CONFIG */
    
    xOffset = 25;
    yOffset = -15;
	hoverMultiply = 2.24; // how much larger the hovered image is in comparison to the original
	bottomGuard = 50; // how far to come up from the bottom of the viewport
    topGuard = 60; // how much space is needed at the top of the viewport
	rightGuard = xOffset + 20; // experiment to find the proper value. include hover box padding and border size
	leftGuard = 20;
	
    // these 2 variable determine popup's distance from the cursor
    // you might want to adjust to get the right result
    
  /* END CONFIG */
  $("img.hover-preview").hover(function(e){
    this.t = this.title;
    this.title = "";  
		
	var windowBottom = $(window).scrollTop() + $(window).height();
	var imgPos = $(this).offset();
	var hoverHeight = $(this).height() * hoverMultiply;
	var hoverWidth = $(this).width() * hoverMultiply;
	
	/* scale the image if it's too big for the window */
	hoverScaleY = ($(window).height() - topGuard - bottomGuard) / hoverHeight;
	hoverScaleX = ($(window).width() -leftGuard - rightGuard) / hoverWidth;
	
	imageScale = hoverScaleY < hoverScaleX ? hoverScaleY : hoverScaleX;
	
	if(imageScale < 1) {
		hoverHeight = hoverHeight * imageScale;
		hoverWidth = hoverWidth * imageScale;
	}
	
	/* check to make sure the bottom of the hovered image will show up above the fold */
	
	if(imgPos.top + hoverHeight + bottomGuard >= windowBottom){
	     hoverY = windowBottom - hoverHeight - bottomGuard;
	} else {
		hoverY = imgPos.top;
	}
	
	if(hoverY <= $(window).scrollTop()) {
		hoverY = $(window).scrollTop() + topGuard;
	}
	
	/* and check right then left to get the image within the window */
	hoverX = imgPos.left + $(this).width();

	/* position to the left or right? */
	
	if(hoverX + hoverWidth + rightGuard >= $(window).width()) {
		hoverX = imgPos.left - hoverWidth - (xOffset*2) -15;
	} 
	
	if(hoverX < 1) {
		hoverX = leftGuard;
	}
	
    var c = (this.t != "") ? "<br/>" + this.t : "";
    var preview_link = $('#' + this.id + '-url')[0];
    $("body").append("<p id='hover-preview'><img src='"+ preview_link.href +"' alt='Loading Image Preview' height='" + hoverHeight + "' width='" + hoverWidth + "' />"+ c +"</p>");                
    $("#hover-preview")
      .css("top",(hoverY + yOffset) + "px")
      .css("left",(hoverX + xOffset) + "px")
      .fadeIn("fast");            
    },
  function(){
    this.title = this.t;  
    $("#hover-preview").remove();
    }); 

};

jdfan’s picture

Left/right no longer left as an exercise to the reader. Hovered image is scaled to fit viewport if it's too large.

rjbrown99’s picture

Status: Active » Needs review
StatusFileSize
new3.44 KB

OK, so here's where we are. I rolled the previous -dev version into a 1.0 release. No major changes, just small code cleanups. I took the code from #13 above and rolled it into a patch, attached here. This is a patch against 1.0.

Can I ask for a few testers? Does this work for you?

rjbrown99’s picture

Here's a completely different patch from #15, which is a version of comment #2 above. This fixes vertical positioning to keep items on the page, but does not address horiziontal off-screen issues.

I'd like feedback on both this comment and #15. What works?

rjbrown99’s picture

StatusFileSize
new928 bytes

Patch

jdfan’s picture

We're using the code from #15 at printcollection.com.

rjbrown99’s picture

I'm having a few issues with #15.

With a fixed width theme, and one of the hover-preview images near the right side, here are the issues:

- In IE7, the hover does not appear. The remainder of the images to the left side (where there is enough space to hover to their right) do appear.

- In Firefox, the image on the right side does correctly hover to the left, but when you are running your mouse over the original it seems to continually be re-positioning the image. You end up seeing the mouse cursor changing back and forth from a pointer/arrow to the small hand/finger. The images to the left side don't do that. Also, if you happen to stop moving the cursor when it is a pointer there is no hover that appears.

marcoka’s picture

StatusFileSize
new1.26 KB
new2.69 KB

my version:

Problem is that an image that is at the bottom gets displayed out of the actual viewport. See Images:

BEFORE: http://www.screencast.com/users/e-anima/folders/Jing/media/7d8e8296-7d37...
AFTER PATCH: http://www.screencast.com/users/e-anima/folders/Jing/media/11a0d4d2-5379...

I modified the .module and the .js. and attached a patch. So now an image will never be displayed outside of the visible viewport.

rjbrown99’s picture

So far patch #20 seems to work the best for me in terms of alignment to the bottom of the browser window. It seems to cleanly fix that across all browsers I tried. It does not yet fix the left/right placement of the image (in my case, the image can still hover off to the right outside of the viewable space of the window.)

I'd love it if someone else could test #20 and provide feedback. Thanks.

eriknewby’s picture

StatusFileSize
new53.8 KB

#20 does indeed work well to keep the preview from "disappearing" below. However, like rjbrown99 states, they still disappear off the right-hand side of the screen.

marcoka’s picture

i will get to that issue in time, because i need that for an actual project of mine too. i will post my patch, patched then :)

rjbrown99’s picture

I'm inclined to want to commit #20, at least to the -dev branch. I'm using it on my site now and it is working quite well. If I don't hear objections I'll do that this weekend.

LightFromArt’s picture

It looks good. Could you commit it not only to development version, but to the main version as well?

papastavros10’s picture

patch #20 work fine vericaly only. Any progress in fixing the horizontal issue? If anyone used a different approach and fixed the bug can please post the patch

rjbrown99’s picture

Title: placement relative to always show on screen (instead of off to the side) » Horizontal image placement is off screen
Category: feature » bug
Status: Needs review » Needs work

I committed #20 to dev. Thank you.
http://drupal.org/cvs?commit=454454

I'm leaving this open and moving to 'needs work' because this only fixes vertical, and we still need a horizontal patch.

marcoka’s picture

yea .back in the game. i am starting to code/fix the vertical problem at the moment. i´ll post when i finish it.

marcoka’s picture

finsihed, unfortunately i can not make a patch because i forked another feature in in (zoom hovered image to 100% on keypress Z), at the moment, depend on a fork of hover_preview. But i post the mousemove function here that is responsible for the horizontal/vertical tracking.

you need to REPLACE the complete $("img.hover-preview").mousemove(function(e){ ..... }); Function with the following

/**************************** Mousemovement *********************************************/
  /********** Track the mouse to prevent loading the image out of the viewport   **********/
  
  //keep track of mouse movement in an image and move preview element
  $("img.hover-preview").mousemove(function(e){
  
    //width & height of the popup with the larger image triggered on hover.
    var elementHeight = $("div#hover-preview-active").outerHeight(true);
    var elementWidth = $("div#hover-preview-active").outerWidth(true);    
       
    //Size of the viewport, meaning the area of the page, that is completely visible.
    var winHeight = $(window).height(); 
    var winWidth = $(window).width();    
    
    //If the page has been scolled, addidtional calculation must be done.
    //Scroll position is the same as the number of pixels that are hidden from view above the scrollable area. 
    //If the scroll bar is at the very top, or if the element is not scrollable, this number will be 0.    
    var scrolledPixelTop = $(window).scrollTop();
    var scrolledPixelLeft = $(window).scrollLeft();  //a site should not be vertically scrollable, but maybe...    
  
    //calculate if image would be loaded outside 
    var calcHeight = winHeight - e.pageY + yOffset + scrolledPixelTop;
    var calcWidth = winWidth - e.pageX + xOffset + scrolledPixelLeft;
    console.log('calcWidth: ' + calcWidth);
    
    //set initial
    var xPosition = e.pageX;
    var yPosition = e.pageY;    
    
    if( calcHeight <= elementHeight ) {
      var yPosition = winHeight - elementHeight + scrolledPixelTop;      
    }    
      
    if( calcWidth <= elementWidth ) {
      var xPosition = winWidth - 2*elementWidth + scrolledPixelLeft;     
    }   
         
    $("div#hover-preview-active")
       .css("top",(yPosition - yOffset) + "px")
       .css("left",(xPosition + xOffset) + "px");
  }); 
rjbrown99’s picture

#29, thank you - I'll roll up a patch and post it back to the issue queue assuming it works. Much appreciated!

rjbrown99’s picture

StatusFileSize
new2.39 KB

I fixed the CSS classes to match the original module and rolled up a patch, but at least for now it's not fully working for me. It does continue to keep the vertical images in the viewport, when they would otherwise appear "beneath the fold".

Horizontally, some of the images that would have otherwise appeared offscreen to the right do appear to the left now, but much further left than they should be. The other issue is for an image at the 'bottom right' corner, where it would have fallen both beneath the fold vertically as well as outside of the viewport horizontally. In that case, it corrects for the vertical but not the horizontal - i.e. they are offscreen to the right.

I don't have a lot of time to test today but here's the patch, rolled against the latest -dev.

marcoka’s picture

i´ll take a look too.

marcoka’s picture

i am asking myself the following question right now: why do we use mousemove() to re-replace the image on movement? Whats the use of that? the mousemove() is troggered on every pixel moved. That raises the cpu load on one of my cores from 2% to 60. But for what? This replacement on mouse movement has no real advantages (only that we waste cpu). I also saw that big sites like istock, shutterstock do used fixed placement. I bet its because of the cpu load. Other weak systems like eepc would not be happy about such unneccessary cpu loads.

Whats your opinion? I pledge to change that.

My suggestion is to eliminate that and only make a fixed placement on hover (checking offscreen too, of course).

This is my current code. But Like always IE has some seriouse issues with the mousemove()

 /**************************** Mousemovement *********************************************/
  /********** Track the mouse to prevent loading the image out of the viewport   **********/
  
  //keep track of mouse movement in an image and move preview element
  $("img.hover-preview").mousemove(function(e){
        
    //width & height of the popup with the larger image triggered on hover.
    var elementHeight = $("#hover-preview-active").outerHeight(true);
    var elementWidth = $("#hover-preview-active").outerWidth(true); 
       
    //Size of the viewport, meaning the area of the page, that is completely visible.
    var winHeight = $(window).height(); 
    var winWidth = $(window).width();  
    
    //If the page has been scolled, addidtional calculation must be done.
    //Scroll position is the same as the number of pixels that are hidden from view above the scrollable area. 
    //If the scroll bar is at the very top, or if the element is not scrollable, this number will be 0.    
    var scrolledPixelTop = $(window).scrollTop();
    var scrolledPixelLeft = $(window).scrollLeft();  //a site should not be vertically scrollable, but maybe...    
  
    //calculate if image would be loaded outside 
    //the width that is avaliable for displaying, could be smaller that the actual image => offscreen
    var calcHeight = winHeight - e.pageY + yOffset + scrolledPixelTop;
    var calcWidth = winWidth - e.pageX - xOffset + scrolledPixelLeft;
    
    //set initial
    var xPosition = e.pageX;
    var yPosition = e.pageY;  
//    console.log('yPosition: ' + yPosition + ' calcHeight: ' + calcHeight + ' winHeight: ' + winHeight + ' elementHeight: ' + elementHeight);
//    console.log('xPosition: ' + xPosition + ' calcWidth: ' + calcWidth + ' winWidth: ' + winWidth + ' elementWidth: ' + elementWidth);
    
    if( calcHeight < elementHeight ) {
      var yPosition = winHeight - elementHeight + yOffset + scrolledPixelTop;    
      //console.log('NEW yPosition' + yPosition);      
    }    
      
    if( calcWidth < elementWidth ) {
      var xPosition = e.pageX - elementWidth - 2*xOffset + scrolledPixelLeft;     
      //console.log('NEW xPosition' + xPosition);      
    }       
   
//    console.log(' yPosition' + yPosition);
//    console.log(' xPosition' + xPosition);
    
    $("#hover-preview-active")
       .css("top", (yPosition - yOffset) + "px")
       .css("left",(xPosition + xOffset) + "px");
    
  }); //end mousemove 
marcoka’s picture

the ie problem is somehow caused if you move the mouse too fast over the image (appears when having multiple images in a row with a small margin), then its not working (ie fires both in and out....). As always in IE only (someone got bored at ms ...). At the moment i have no idea how this is possible to fix.

marcoka’s picture

StatusFileSize
new4.91 KB

fixed ie problem, on fast mouse movement there are still some problems because images could jump, because of cpu intensive offset/re-replace calculations.

I am going for a version without the re-replacement now.
I attached the current version with re-replacement.

@rjbrown99, i would you be interested to merge my fork with your version some time (when i finish my whole project)? I added an additional feature to 100% crop zoom the preview (for sharpening/quality rate of an image). This is useful for something like stock/foto downloads.

marcoka’s picture

Status: Needs work » Needs review
rjbrown99’s picture

I'm certainly open to additions to the base module. We may want to consider a basic management interface to allow enabling/disabling of different effects. I'll have a look at the new JS on my dev site in the next few days. Thanks for all of your contributions!

splotchy’s picture

First of all thanks for this great module.

#35 didn't work for me, I got a broken image at the bottom of the page see attach

#29 & #33 do not work for me either I get no hover image only text

Patch #20 gives me

Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting ')' in /home/pcom3a/public_html/sites/all/modules/hover_preview/hover_preview.module on line 83

currently using #13 as it does the job well enough :)

on 3-p.com.au

Thanks guys!

splotchy’s picture

StatusFileSize
new3.06 KB
rjbrown99’s picture

I committed a fix for this to the -dev branch. Tested in Firefox, Chrome, and IE 7/8/9RC. The fix was created by jrp and it is not one of the previous patches in the issue queue. I'd like to have some feedback if possible - if it's working for everyone I'll roll a new 6.x-1.1 module up with the fixes. So far so good for me and I have it in production.

http://drupal.org/cvs?commit=499020

greymalkingallery’s picture

I just installed the -dev version on my site and it works very nicely. Thank you. :)

Poieo’s picture

This fix doesn't appear to have made it into the 7.x branch? What would it take to get it in there?

marcoka’s picture

i rewrote the whole js code to be more performant, moving the image with the mouse is not really a performant idea and unneccessary.
in action here: http://www.texturecase.com/textur/beton-waschbeton-0013-1-4
when i move that site to d7 i will try to supply a patch for d7 version.

rjbrown99’s picture

#43: Can you also supply a patch for 6.x, assuming it does not suffer from the image placement off screen? Thank you.

marcoka’s picture

rjbrown, unfortunately i can not make a diff patch simply because i hacked the whole module too.

cimo75’s picture

+1 for D7

jakonore’s picture

Version: 6.x-1.x-dev » 7.x-1.x-dev
Status: Needs review » Active

Since the problem seems to be solved for 6.X version should we change the version to 7.X now?
I am willing to help providing a patch but might need some explanation of the current code.

dready2011’s picture

Any news on this for D7?

MrNeko’s picture

Hi, I realized the latest version for d7 still doesn't prevent hovered image to display offscreen. Is there any patch to this at the moment?

marcoka’s picture

check this out.i quickly wrote this. we could merge that into this one, but since this module here uses a 3rd party script, one would need to understand it and fork it too.
http://drupal.org/project/image_preview

imoreno’s picture

Any updates with this one?

Itzhak

klausenlie’s picture

Hi!

I`m not really writing about this thread, but this one: https://drupal.org/node/1932340 but I`m not getting much response from people there.
Has anybody got any contact with some active maintainers that I can communicate with or to know more about the status on the thread?

Any help is appriciated!

zombirus’s picture

marcoka, your new module is really good!

Philou88’s picture

I really prefer this module 'Hover Preview for ImageCache'.
It's because you have no key 'Z' (heavy to do) to click on for larger image, and more, only in the middle!
Please, it will be nice to solve this thread in D7.
Thanks in advance,

  • rjbrown99 committed 872fdd7 on 8.x-1.x
    #729648 by e-anima, jdfan: Fix vertical positioning of hover images
    
    
  • rjbrown99 committed ffdde9e on 8.x-1.x
    #729648 by jrp, e-anima, jdfan, rjbrown99: Fix horizontal hover...
Andre-B’s picture

Issue summary: View changes
Status: Active » Closed (outdated)

This was already on 7.x-1.x-dev closing this one for now. new development / features should go in a new issue.