Fix clicking and dragging the scrollbar rails with large margin values.

Fix initial rail height/width calculation: Set the rails to display:block temporarily to correctly calculate percentage margins
Account for scrolltop/left on the document.
This commit is contained in:
Jaron Kennel 2015-04-10 11:04:08 -04:00
parent 2cd65684e2
commit a40ab40695
6 changed files with 52 additions and 25 deletions

View File

@ -6,27 +6,39 @@
<link href="../dist/css/perfect-scrollbar.css" rel="stylesheet">
<script src="../dist/js/perfect-scrollbar.js"></script>
<style>
.contentHolder { position:relative; margin:0px auto; padding:0px; width: 600px; height: 400px; overflow: auto; }
.contentHolder .content { background-image: url('./azusa.jpg'); width: 1280px; height: 720px; }
.spacer { text-align:center }
h1 { text-align: center; }
.container { position:relative; margin:0px auto; padding:0px; width: 600px; height: 400px; overflow: auto; }
.container .content { background-image: url('./azusa.jpg'); width: 1280px; height: 720px; }
.ps-scrollbar-x-rail {
margin: 0 3px;
.large-margin .ps-scrollbar-x-rail {
margin: 0 25%;
opacity: 0.5;
background-color: #eee;
}
.ps-scrollbar-y-rail {
margin: 3px 0;
.large-margin .ps-scrollbar-y-rail {
margin: 100px 0;
opacity: 0.5;
background-color: #eee;
}
</style>
</head>
<body>
<div id="Default" class="contentHolder">
<h1>Default</h1>
<div class="container">
<div class="content">
</div>
</div>
<h1>Margins</h1>
<div class="container large-margin">
<div class="content">
</div>
</div>
<script>
var $ = document.querySelector.bind(document);
window.onload = function () {
Ps.initialize($('#Default'));
[].forEach.call(document.querySelectorAll('.container'), function (el) {
Ps.initialize(el);
});
};
</script>
</body>

View File

@ -16,8 +16,8 @@ function bindClickRailHandler(element, i) {
i.event.bind(i.scrollbarY, 'click', stopPropagation);
i.event.bind(i.scrollbarYRail, 'click', function (e) {
var halfOfScrollbarLength = h.toInt(i.scrollbarYHeight / 2);
var positionTop = e.pageY - pageOffset(i.scrollbarYRail).top - halfOfScrollbarLength;
var maxPositionTop = i.containerHeight - i.scrollbarYHeight;
var positionTop = i.railYRatio * (e.pageY - window.scrollY - pageOffset(i.scrollbarYRail).top - halfOfScrollbarLength);
var maxPositionTop = i.railYRatio * (i.railYHeight - i.scrollbarYHeight);
var positionRatio = positionTop / maxPositionTop;
if (positionRatio < 0) {
@ -33,9 +33,8 @@ function bindClickRailHandler(element, i) {
i.event.bind(i.scrollbarX, 'click', stopPropagation);
i.event.bind(i.scrollbarXRail, 'click', function (e) {
var halfOfScrollbarLength = h.toInt(i.scrollbarXWidth / 2);
var positionLeft = e.pageX - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength;
console.log(e.pageX, i.scrollbarXRail.offsetLeft);
var maxPositionLeft = i.containerWidth - i.scrollbarXWidth;
var positionLeft = i.railXRatio * (e.pageX - window.scrollX - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength);
var maxPositionLeft = i.railXRatio * (i.railXWidth - i.scrollbarXWidth);
var positionRatio = positionLeft / maxPositionLeft;
if (positionRatio < 0) {

View File

@ -13,8 +13,8 @@ function bindMouseScrollXHandler(element, i) {
var currentPageX = null;
function updateScrollLeft(deltaX) {
var newLeft = currentLeft + deltaX;
var maxLeft = i.containerWidth - i.scrollbarXWidth;
var newLeft = currentLeft + (deltaX * i.railXRatio);
var maxLeft = i.scrollbarXRail.getBoundingClientRect().left + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
if (newLeft < 0) {
i.scrollbarXLeft = 0;
@ -24,7 +24,7 @@ function bindMouseScrollXHandler(element, i) {
i.scrollbarXLeft = newLeft;
}
var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - i.scrollbarXWidth));
var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth)));
element.scrollLeft = scrollLeft;
}
@ -42,7 +42,7 @@ function bindMouseScrollXHandler(element, i) {
i.event.bind(i.scrollbarX, 'mousedown', function (e) {
currentPageX = e.pageX;
currentLeft = h.toInt(d.css(i.scrollbarX, 'left'));
currentLeft = h.toInt(d.css(i.scrollbarX, 'left')) * i.railXRatio;
h.startScrolling(element, 'x');
i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
@ -58,8 +58,8 @@ function bindMouseScrollYHandler(element, i) {
var currentPageY = null;
function updateScrollTop(deltaY) {
var newTop = currentTop + deltaY;
var maxTop = i.containerHeight - i.scrollbarYHeight;
var newTop = currentTop + (deltaY * i.railYRatio);
var maxTop = i.scrollbarYRail.getBoundingClientRect().top + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
if (newTop < 0) {
i.scrollbarYTop = 0;
@ -69,7 +69,7 @@ function bindMouseScrollYHandler(element, i) {
i.scrollbarYTop = newTop;
}
var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - i.scrollbarYHeight));
var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
element.scrollTop = scrollTop;
}
@ -87,7 +87,7 @@ function bindMouseScrollYHandler(element, i) {
i.event.bind(i.scrollbarY, 'mousedown', function (e) {
currentPageY = e.pageY;
currentTop = h.toInt(d.css(i.scrollbarY, 'top'));
currentTop = h.toInt(d.css(i.scrollbarY, 'top')) * i.railYRatio;
h.startScrolling(element, 'y');
i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);

View File

@ -33,8 +33,12 @@ function Instance(element) {
i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : h.toInt(d.css(i.scrollbarXRail, 'top'));
i.railBorderXWidth = h.toInt(d.css(i.scrollbarXRail, 'borderLeftWidth')) + h.toInt(d.css(i.scrollbarXRail, 'borderRightWidth'));
// Set rail to display:block to calculate margins
d.css(i.scrollbarXRail, 'display', 'block');
i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
d.css(i.scrollbarXRail, 'display', '');
i.railXWidth = null;
i.railXRatio = null;
i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element);
i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
@ -46,8 +50,11 @@ function Instance(element) {
i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : h.toInt(d.css(i.scrollbarYRail, 'left'));
i.scrollbarYOuterWidth = i.isRtl ? h.outerWidth(i.scrollbarY) : null;
i.railBorderYWidth = h.toInt(d.css(i.scrollbarYRail, 'borderTopWidth')) + h.toInt(d.css(i.scrollbarYRail, 'borderBottomWidth'));
d.css(i.scrollbarYRail, 'display', 'block');
i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
d.css(i.scrollbarYRail, 'display', '');
i.railYHeight = null;
i.railYRatio = null;
}
function getId(element) {

View File

@ -70,6 +70,7 @@ module.exports = function (element) {
if (!i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth) {
i.scrollbarXActive = true;
i.railXWidth = i.containerWidth - i.railXMarginWidth;
i.railXRatio = i.containerWidth / i.railXWidth;
i.scrollbarXWidth = getThumbSize(i, h.toInt(i.railXWidth * i.containerWidth / i.contentWidth));
i.scrollbarXLeft = h.toInt(element.scrollLeft * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
} else {
@ -82,6 +83,7 @@ module.exports = function (element) {
if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) {
i.scrollbarYActive = true;
i.railYHeight = i.containerHeight - i.railYMarginHeight;
i.railYRatio = i.containerHeight / i.railYHeight;
i.scrollbarYHeight = getThumbSize(i, h.toInt(i.railYHeight * i.containerHeight / i.contentHeight));
i.scrollbarYTop = h.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight));
} else {

View File

@ -4,18 +4,25 @@
'use strict';
var d = require('../lib/dom')
, h = require('../lib/helper')
, instances = require('./instances')
, updateGeometry = require('./update-geometry');
module.exports = function (element) {
var i = instances.get(element);
// Recalculate rail margins
d.css(i.scrollbarXRail, 'display', 'block');
d.css(i.scrollbarYRail, 'display', 'block');
i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
// Hide scrollbars not to affect scrollWidth and scrollHeight
d.css(i.scrollbarXRail, 'display', 'none');
d.css(i.scrollbarYRail, 'display', 'none');
updateGeometry(element);
d.css(i.scrollbarXRail, 'display', 'block');
d.css(i.scrollbarYRail, 'display', 'block');
d.css(i.scrollbarXRail, 'display', '');
d.css(i.scrollbarYRail, 'display', '');
};