Skip to content

Commit

Permalink
Fix clicking and dragging the scrollbar rails with large margin values.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jaronkk committed Apr 13, 2015
1 parent 2cd6568 commit a40ab40
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 25 deletions.
32 changes: 22 additions & 10 deletions examples/scrollbars-with-margin.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
9 changes: 4 additions & 5 deletions src/js/plugin/handler/click-rail.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
16 changes: 8 additions & 8 deletions src/js/plugin/handler/drag-scrollbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions src/js/plugin/instances.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions src/js/plugin/update-geometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
11 changes: 9 additions & 2 deletions src/js/plugin/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -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', '');
};

0 comments on commit a40ab40

Please sign in to comment.