Reputation: 8944
Here's a long one. I'm trying to implement horizontal scrolling in my site. It's working fine in Safari and Chrome, but not in Firefox (I'll not get started on IE's issues just yet).
From what I can tell, Webkit is using the relative position of the scroll bar grabber div, while firefox is taking it's position relative to the document.
You can test it here to see what's happening.
Here's the CSS for the scroll bar
/* The Scrollbar */
#scrollbar
{
position: relative;
width: 70%;
display: block;
margin: 0px auto;
border: #444444 1px solid;
border-width: 0 0 1px 0;
overflow: visible;
}
#grabber
{
position: relative;
top: 8px;
left: 0px;
height: 20px;
display: block;
background: url(assets/grabber-left.png) no-repeat;
}
#grabber-end
{
height: inherit;
width: 50%;
background: url(assets/grabber-right.png) no-repeat;
background-position: 100% 0;
float: right;
}
And the jQuery that powers it
var grabberClicked = false;
var dragStart;
var grabberStart;
var ratio;
var scrollBound;
var totalWidth = 0;
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$(document).ready(function(){
$("#projects").width(getTotalWidth());
setup();
$("#grabber").mousedown(startScroll);
$(window).mouseup(endScroll);
$("#viewport").scroll(positionGrabber);
$(window).resize(setup);
});
function getTotalWidth(){
$(".project").each(function(){
totalWidth += $(this).width();
totalWidth += parseInt($(this).css("marginLeft")) * 2;
})
return totalWidth;
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function setup(){
ratio = $("#viewport").width() / $("#projects").width();
// grabber width
$("#grabber").width( $("#scrollbar").width() * ratio );
scrollBound = $("#scrollbar").width() - $("#grabber").width();
// incase the user resizes the window, position the grabber accordingly
positionGrabber();
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function startScroll(event){
$(window).bind('mousemove', scroll);
var position = $("#scrollbar").position();
dragStart = event.pageX - position.left;
grabberStart = parseInt($("#grabber").css("left"));
$("#feedback").html($("#grabber").position().left);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function endScroll(event){
$(window).unbind('mousemove', scroll);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function scroll(event){
var newPos = grabberStart + (event.pageX - dragStart);
//$("#feedback").html($("#grabber").position().left +" // "+ newPos);
// bounds
newPos = (newPos > 0) ? newPos : 0;
newPos = (newPos < scrollBound) ? newPos : scrollBound;
viewportPos = ( $("#projects").width() * ( newPos / $("#scrollbar").width() ) );
$("#viewport").scrollLeft(viewportPos);
$("#grabber").css("left", newPos);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function positionGrabber(event){
var grabberPos = $("#scrollbar").width() * ($("#viewport").scrollLeft() / $("#projects").width());
$("#grabber").css("left", grabberPos);
}
Any ideas? I know I should know the answer to this, but I've been staring at it so long I'm blind to it.
cheers
Upvotes: 1
Views: 1006
Reputation: 86453
I messed around a bit with your code, I think the problem is that position.left
returns the position of the object relative to the window and it was returning the scrollbar position. So just changing the position variable from #scrollbar
to #grabber
worked for me.
var position = $("#grabber").position();
and because of this, you don't need to save the grabberStart
position
Lastly, for some reason, and this took me a while to figure out, IE doesn't like binding to window
events. So I switched them to document
and BAM! IE is working perfectly.
Here is you script updated with the changes I mentioned. Nice looking site by the way!
// **********************************************
// Throll: Toms Horizontal Scroll
// Developer: Tom Elders
// Contact: [email protected]
// **********************************************
// File: throll.1.0.js
// Description:
// CSS and JS horizontal scriolling that doesn't
// break the browers native functionality.
//
// Copyright 2010, Tom Elders
//
// **********************************************
var grabberClicked = false;
var dragStart;
var ratio;
var scrollBound;
var totalWidth = 0;
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$(document).ready(function(){
$("#projects").width(getTotalWidth());
setup();
$("#grabber").mousedown(startScroll);
$(document).mouseup(endScroll);
$("#viewport").scroll(positionGrabber);
$(window).resize(setup);
});
function getTotalWidth(){
$(".project").each(function(){
totalWidth += $(this).width();
totalWidth += parseInt($(this).css("marginLeft")) * 2;
})
return totalWidth;
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function setup(){
ratio = $("#viewport").width() / $("#projects").width();
// grabber width
$("#grabber").width( $("#scrollbar").width() * ratio );
scrollBound = $("#scrollbar").width() - $("#grabber").width();
// incase the user resizes the window, position the grabber accordingly
positionGrabber();
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function startScroll(event){
$(document).bind('mousemove', scroll);
var position = $("#grabber").position();
dragStart = event.pageX - position.left;
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function endScroll(event){
$(document).unbind('mousemove', scroll);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function scroll(event){
var newPos = event.pageX - dragStart;
// bounds
newPos = (newPos > 0) ? newPos : 0;
newPos = (newPos < scrollBound) ? newPos : scrollBound;
viewportPos = ( $("#projects").width() * ( newPos / $("#scrollbar").width() ) );
$("#viewport").scrollLeft(viewportPos);
$("#grabber").css("left", newPos);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function positionGrabber(event){
var grabberPos = $("#scrollbar").width() * ($("#viewport").scrollLeft() / $("#projects").width());
$("#grabber").css("left", grabberPos);
}
Upvotes: 1