jQuery .offset() not retrieving correct position
Asked Answered
W

2

5

I'm working on a site which dynamically creates facebook-like buttons via PHP. However, the <div> that the buttons are contained in needs to have the CSS property overflow: hidden; This is the only way I've found that works to make a two-column format which forces both columns to expand to be the length of the longest one. The only problem with this method is that any facebook-like buttons placed near the bottom of the container get clipped when someone clicks on them and they expand.

Here's the way I've tried to solve this issue:

  1. Using jQuery, I loop through all facebook like buttons on the page and calculate their document offset using the offset() method.

  2. I then clone() each button as well as give it absolute positioning and the calculated offset using jQuery's css() method. I hope that each cloned button will be placed in the same position of the button it was cloned from when I append it to the document.

  3. Finally, I change each old facebook-like button's css to visibility: hidden; in order to make it invisible but still take up the space it would have previously on the page. I add the clones of the facebook-like buttons to a div without the overflow: hidden; property using the appendTo() function.

Here's my entire code for this process:

// Replaces functional facebook recommend buttons with identical ones
// in a div where they won't get clipped when they expand.
// Hides the old buttons so space is still left for new ones
$(window).load(function(){
    $(".fb-recommend").each(function(){ // cycle through each recommend button
        var offset = $(this).offset(); // calculate offset of each button
        var newButton = $(this).clone(); // clone the button
        newButton.css({'position':'absolute', 'left':offset.left, 'top':offset.top});
        $(this).css("visibility","hidden"); // hide the old button
        newButton.appendTo("#wrapper"); // put the new button in the wrapper where it won't get clipped
    });
});

At the end of all this, I expect to have clones of each button placed where the old button was but in a different <div>. The whole process works, except that the cloned facebook-like buttons are appearing at a slightly different position than the ones they were cloned from (as PitaJ points out they seem to be off by vertical offset multiples of around 39px). You can view the issue here:

LINK TO TEST WEBSITE

As you can see, the first button is placed in the correct location (the empty space filled by its hidden clone) but the other offsets were not calculated correctly.

I'd appreciate any ideas or help offered. Let me know if you'd like me to explain better or post more code!

Edit: I figured I'd post the CSS for the facebook-like buttons here (even though all I'm changing is the margin):

#content .fb-recommend {
    margin: 15px 0 5px 0;
}

Edit 2: As per UnLoco's suggestion, I added a min-height property to the fb-reccommend CSS and commented out the line of code that was hiding the old buttons so it's easier to see the problem (which is still there, though slightly lessened. The CSS now looks like this:

#content .fb-recommend {
    margin: 15px 0 5px 0;
    min-height: 39px;
}

Edit 3: The problem appears to have been solved in all browsers but IE by changing the CSS to this:

.fb-recommend {
    min-height: 24px;  // I used 24 because the fb-buttons are 24px in height
}

Final Edit? This seems to work on all browsers on my end, including IE:

.fb-recommend {
    min-height: 39px;
}

I'm thinking now that the 39 might have come from the 15px margin of the old fb-button + its 24px height. I think I can get around it by simply setting the height to be 39px and not having a margin.

Wenda answered 18/8, 2012 at 21:10 Comment(4)
They're off by multiples of 39pxCandlewood
@Candlewood how'd you figure out the exact number of pixels? Any idea why that's happening? By trial and error I set my top CSS attribute to be offset.top + i*40, where i was passed in by the .each function, and this seemed to get it pretty close.Wenda
I just used trial and error to get the 39, but I can't figure out why it's that many pixels off.Candlewood
now i get it bro, (i deleted older comments) this is because you are retrieving the offset before the iframes actually load. just add a css rule like this div.fb-recommend{min-height:39px}Pamplona
P
6

this is because you are retrieving the offset before the fb iframes actually load. just add a css rule like this
div.fb-recommend{min-height:39px}

Pamplona answered 19/8, 2012 at 4:34 Comment(9)
I think you're on the right track. I added the CSS rule and commented out the line of code that was hiding the old buttons - there's still a bit of an offset from where they should be, but a much smaller one now (you can see it in that link). Any idea what might be causing that?Wenda
fine tune the min-height value, set it to let's say 40pxPamplona
Changing the min-height value isn't having an effect on their offset. Even if I make the min-height something huge (say 200) it just adds more space underneath the text, and doesn't affect the button offset.Wenda
that's because you wrote the rule like this #content .fb-recommend it doesn't match the newly cloned divs ! just make it to simply .fb-recommendPamplona
Thanks man, you're the best! After I made that CSS change and removed the margin style from the fb-like button everything seems to have worked out. It looks good on my end, would you mind taking a quick look on a couple of your browsers to make sure it's appearing right for you? I really appreciate the help and will give you the check as soon as you verify that it's working as expected. :)Wenda
looks great on firefox and chrome but not on IEPamplona
why does IE always have to be so difficult?!? I'm not really sure where to go from here since it seems to be working everywhere else...Wenda
I think I may have solved it by changing the min-height from 24px back to 39px - can you take a look?Wenda
Thanks so much for your help! I really appreciate you following through with this. Enjoy the bounty (in a day or so) for all your hard work!Wenda
C
3

I believe you're problem is some odd jQuery weirdness.

To fix this, simple change your code to this:

$(window).load(function(){
    $(".fb-recommend").each(function(index){ // cycle through each recommend button
        var offset = $(this).offset(); // calculate offset of each button
        var newButton = $(this).clone(); // clone the button
        newButton.css({'position':'absolute', 'left':offset.left, 'top':offset.top + (39*index)});
        $(this).css("visibility","hidden"); // hide the old button
        newButton.appendTo("#wrapper"); // put the new button in the wrapper where it won't get clipped
    });
});

This will account for the weird offset problem.

Candlewood answered 18/8, 2012 at 22:13 Comment(1)
Thanks for this. It's what I'd been doing before (except I had an offset of 40 instead of 39). I'm going to put a bounty on this in a couple days to see if anyone else has any ideas about why it might be happening. If nobody else has any more insight then the correct answer and bounty is yours since you provided a working solution.Wenda

© 2022 - 2024 — McMap. All rights reserved.