jQuery code working in Safari but not Firefox
I'm attempting to use a mixture of jQuery and CSS to make the sand in an hourglass appear to flow as you scroll down the page. I basically have two 'sand' images, and use jQuery to change the height of their containers as the user scrolls.
<!-- Load jQuery -->
<script src="jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
<!-- Handle Hourglass Scrolling -->
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
// Set value of topStart and bottomStart to equal to y-position of the equivilent divs
var topStart = parseInt($('#top-sand').css('top'));
var bottomStart = parseInt($('#bottom-sand').css('top'));
// Calculate the maximum height of the sand relative to the window size
var sandHeight = $(window).height()*0.22;
// setValues sets positions based on window size
function setValues() {
topStart = parseInt($('#top-sand').css('top'));
bottomStart = parseInt($('#bottom-sand').css('top'));
sandHeight = $(window).height()*0.22;
var hourglassWidth = $('#hourglass #outline img').css('width');
var leftMargin = $(window).width()*0.5+ 320;
$('#top-sand').height(22+"%");
$('#top-sand img').height(sandHeight)
$('#bottom-sand img').height(sandHeight)
$('#hourglass').css({left:leftMargin+"px"})
$('#trace').text(hourglassWidth)
// contentMarginLeft = $('#hourglass #outline').width();
// $('#content').text(contentMarginLeft);
// css({"margin-left": contentMarginLeft + "px"});
};
setValues();
// This listens for a window scroll event and then handles the height and position of the sand in the Hourglass
$(window).scroll(function () {
// Calculating the position of the scrollbar
var doc = $("body"),
scrollPosition = $("body").scrollTop(),
pageSize = $("body").height(),
windowSize = $(window).height(),
fullScroll = pageSize - windowSize;
percentageScrolled = (scrollPosition / fullScroll);
// Calculating the Y-positions of the two sand piles
var topPosition = topStart+(22*percentageScrolled);
var bottomPosition = bottomStart-(22*percentageScrolled);
// Updating the sand piles
$('#top-sand').height(22-(22*percentageScrolled)+"%")
.css({top: topPosition+"%"});
$('#bottom-sand').height(22*percentageScrolled+"%")
.css({top:bottomPosition+"%"});
});
// This listens for a window resize event and then reconfigures the layout
$(window).bind('resize', function() {
// Reconfigure layout
});
开发者_如何学JAVA });
</script>
It's been working fine in Safari (although every so often there's a glitch where the height of the top image changes, but it's y position doesn't), but it hasn't been working in Firefox at all. You can see the site here http://www.chris-armstrong.com/ticktalk
I'm pretty new to jQuery, so apologies if it's a complete noob error.
Thanks in advance.
OK, I got it working! You are going to have to look at my source to see what I did because I changed so much, but the basis of your problem was from the fact that the "scrollable" element is different on different platforms/browsers.
Sometimes it is the html
element, other times it is the body
element. I used a few lines of code from the scrollTo Plugin to take care of that. I used CSS to position the hourglass. And I used colored div blocks to give the appearance that the sand was moving. You no longer need to handle browser sizing events (which would drive you crazy in IE, trust me :)
Here is the working demo.
I tested in Safari and FF on the Mac, but it should work correctly in IE7+.
Here is the jQuery code (not including the snippet from scrollTo):
<script type="text/javascript">
$(function(){
var low = 28,
high = 50,
max = 86.5,
range = high - low,
$mtop = $("#mask-top"),
$mbottom = $("#sandy-bottom")
scroller = $()._scrollable(); // Uses part of the scrollTo plugin
$(window).scroll(function(e){
var scrollTop = $(scroller).scrollTop(),
bodyHeight = document.body.scrollHeight,
itemHeight = $('#outline').outerHeight();
var percentScrolled = scrollTop / (bodyHeight - itemHeight);
percentScrolled = Math.floor(percentScrolled * 100) / 100;
var newHeight = (range * percentScrolled);
newHeight = Math.floor(newHeight * 10) / 10;
$mtop.height( (newHeight + low) + "%" );
$mbottom.css( 'top', (max - newHeight) + "%" );
})
})
</script>
Here is the updated HTML which I moved to be a child of body
:
<div id="hourglass">
<img id="outline" src="img/hourglass-outline.png" width="634" height"1080" alt="Hourglass Outline" />
<!-- A new image I created based on your two-->
<img id="sandy" src="hourglass-insides.png" width="634" height="1080" />
<div class="mask" id="mask-top" ></div>
<img id="sandy-bottom" src="hourglass-insides.png" width="634" height="1080" />
</div>
And for those who care to look, here is the CSS I used to position the hourglass:
<style type="text/css" media="screen">
#hourglass {
left: 0; top: 0; bottom: 0; right: 0;
}
#outline, #sandy, #sandy-bottom {
position: fixed;
top: 0;
height: 100%;
left: 50% !important;
margin: 0;
margin-left: 215px;
max-height: 100%;
min-height: 100%;
width: auto;
}
#sandy {
top: -32%;
}
#sandy-bottom {
top: 86.5%;
}
.mask {
background: #262B28;
position: fixed;
width: 100%;
left: 0;
right: 0;
}
#mask-top {
top: 0;
height: 28%;
}
</style>
Some thoughts to ponder:
Prefer jQuery's positioning methods to accessing CSS values directly. For example, use
.offset()
,.position()
, etc. instead of.css("top")
. jQuery's methods are more portable across browsers, and will return numbers, not strings. See http://docs.jquery.com/CSS.Case in point:
topStart = parseInt($('#top-sand').css('top'))
above, and many others.If you must obtain a positioning metric via a CSS attribute, make sure to
(1) always convert it to a number, e.g. with
parseInt()
. JavaScript's strings silently convert -- or not -- to numbers in obscure ways. Always be explicit about what you want to treat as a number.(2) account for the case where there are units in the CSS value, e.g. as in '100px'.
Example:
var hourglassWidth = $('#hourglass #outline img').css('width')
above.Watch out for fractional values. In
$('#hourglass').css({left:leftMargin+"px"})
above, what happens if leftMargin is not an integer (has a decimal point?)Your best bet might be to single-step with firebug, and watch the positioning variables as they change from line to line, and compare with your expectations.
精彩评论