Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25e5be13ff | ||
|
|
f683b01959 | ||
|
|
6d2f203441 | ||
|
|
a4808f662e | ||
|
|
98fa15167a | ||
|
|
06929ae685 | ||
|
|
aa63ff0370 | ||
|
|
c7ddde69c2 | ||
|
|
69e3fb2688 | ||
|
|
fad7f8b4a6 | ||
|
|
0deb4c9bc7 | ||
|
|
11fcd09a99 | ||
|
|
0fc5c69b3f | ||
|
|
898928b686 | ||
|
|
ce7146121f | ||
|
|
908cee5490 | ||
|
|
b3880ca638 | ||
|
|
7123891d4d | ||
|
|
4c00a7fdb9 | ||
|
|
3719dd614c | ||
|
|
68dbc427ea | ||
|
|
34135d6ef0 | ||
|
|
0ab95f2d57 |
@@ -1,6 +1,5 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.12
|
||||
- 4
|
||||
deploy:
|
||||
provider: releases
|
||||
|
||||
@@ -328,10 +328,6 @@ The number of pixels the content width can surpass the container width without e
|
||||
The number of pixels the content height can surpass the container height without enabling the Y axis scroll bar. Allows some "wiggle room" or "offset break", so that Y axis scroll bar is not enabled just because of a few pixels.
|
||||
**Default**: `0`
|
||||
|
||||
### stopPropagationOnClick
|
||||
When set to false, when clicking on a rail, the click event will be allowed to propagate.
|
||||
**Default**: `true`
|
||||
|
||||
### theme
|
||||
A string. It's a class name added to the container element. The class name is prepended with `ps-theme-`. So default theme class name is `ps-theme-default`. In order to create custom themes with scss use `ps-container($theme)` mixin, where `$theme` is a scss map.
|
||||
**Default**: `'default'`
|
||||
|
||||
@@ -11,17 +11,28 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="Default" class="contentHolder">
|
||||
<div id="container" class="contentHolder">
|
||||
<div class="content">
|
||||
</div>
|
||||
</div>
|
||||
<p style='text-align: center'>
|
||||
<button id='default'>default</button>
|
||||
<button id='custom'>custom</button>
|
||||
</p>
|
||||
<script>
|
||||
var $ = document.querySelector.bind(document);
|
||||
var container = $('#container');
|
||||
window.onload = function () {
|
||||
Ps.initialize($('#Default'), {
|
||||
theme: 'square'
|
||||
});
|
||||
Ps.initialize(container, { theme: 'square' });
|
||||
};
|
||||
$('#default').addEventListener('click', function () {
|
||||
Ps.destroy(container);
|
||||
Ps.initialize(container);
|
||||
});
|
||||
$('#custom').addEventListener('click', function () {
|
||||
Ps.destroy(container);
|
||||
Ps.initialize(container, { theme: 'square' });
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
63
examples/infinite-scroll.html
Normal file
63
examples/infinite-scroll.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>perfect-scrollbar example</title>
|
||||
<link href="../dist/css/perfect-scrollbar.css" rel="stylesheet">
|
||||
<script src="../dist/js/perfect-scrollbar.js"></script>
|
||||
<style>
|
||||
#Default {
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
background-color: #f1f1f1;
|
||||
border: 1px solid blue;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
}
|
||||
.entryPlaceholder {
|
||||
height: 48px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="Default">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var x = 0;
|
||||
var $ = document.querySelector.bind(document);
|
||||
window.onload = function () {
|
||||
// show some initial data
|
||||
for(var i = 0; i < 10; i++) {
|
||||
$('#Default').innerHTML += '<div class="entryPlaceholder">Entry #' + (x++) + '</div>';
|
||||
}
|
||||
Ps.initialize($('#Default'));
|
||||
|
||||
};
|
||||
|
||||
var isProgramaticallyTriggered = false;
|
||||
var addEntries = function(num) {
|
||||
for(var i = 0; i < num; i++) {
|
||||
$('#Default').innerHTML += '<div class="entryPlaceholder">Entry #' + (x++) + '</div>';
|
||||
}
|
||||
|
||||
isProgramaticallyTriggered = true;
|
||||
Ps.update($('#Default'));
|
||||
isProgramaticallyTriggered = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// on scroll, add more entries
|
||||
document.addEventListener('ps-scroll-y', function(e) {
|
||||
if (!isProgramaticallyTriggered) {
|
||||
console.debug("user scrolled to pos: ", $('#Default').scrollTop);
|
||||
addEntries(1);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
12
package.json
12
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "perfect-scrollbar",
|
||||
"version": "0.6.12",
|
||||
"version": "0.6.14",
|
||||
"description": "Minimalistic but perfect custom scrollbar plugin",
|
||||
"author": "Hyunje Alex Jun <me@noraesae.net>",
|
||||
"contributors": [
|
||||
@@ -30,7 +30,8 @@
|
||||
"dist",
|
||||
"src",
|
||||
"index.js",
|
||||
"jquery.js"
|
||||
"jquery.js",
|
||||
"perfect-scrollbar.d.ts"
|
||||
],
|
||||
"devDependencies": {
|
||||
"browserify": "^11.2.0",
|
||||
@@ -48,6 +49,13 @@
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0"
|
||||
},
|
||||
"jspm": {
|
||||
"main": "./index.js",
|
||||
"dependencies": {
|
||||
"jquery": "npm:jquery"
|
||||
}
|
||||
},
|
||||
"typings": "perfect-scrollbar.d.ts",
|
||||
"scripts": {
|
||||
"test": "gulp",
|
||||
"before-deploy": "gulp && gulp compress",
|
||||
|
||||
29
perfect-scrollbar.d.ts
vendored
Normal file
29
perfect-scrollbar.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
interface PerfectScrollbarOptions {
|
||||
wheelSpeed?: number;
|
||||
wheelPropagation?: boolean;
|
||||
swipePropagation?: boolean;
|
||||
minScrollbarLength?: number;
|
||||
maxScrollbarLength?: number;
|
||||
useBothWheelAxes?: boolean;
|
||||
useKeyboard?: boolean;
|
||||
suppressScrollX?: boolean;
|
||||
suppressScrollY?: boolean;
|
||||
scrollXMarginOffset?: number;
|
||||
scrollYMarginOffset?: number;
|
||||
}
|
||||
|
||||
interface PerfectScrollbar {
|
||||
initialize(container: HTMLElement, options?: PerfectScrollbarOptions);
|
||||
update(container: HTMLElement);
|
||||
destroy(container: HTMLElement);
|
||||
}
|
||||
|
||||
interface JQuery {
|
||||
perfectScrollbar(options?: PerfectScrollbarOptions): JQuery;
|
||||
}
|
||||
|
||||
declare var ps: PerfectScrollbar;
|
||||
|
||||
declare module "perfect-scrollbar" {
|
||||
export = ps;
|
||||
}
|
||||
@@ -24,17 +24,18 @@
|
||||
|
||||
@mixin in-scrolling($theme) {
|
||||
&.ps-in-scrolling {
|
||||
pointer-events: none;
|
||||
&.ps-x > .ps-scrollbar-x-rail {
|
||||
@include scrollbar-rail-hover($theme);
|
||||
> .ps-scrollbar-x {
|
||||
@include scrollbar-hover($theme);
|
||||
height: map_get($theme, scrollbar-x-hover-height);
|
||||
}
|
||||
}
|
||||
&.ps-y > .ps-scrollbar-y-rail {
|
||||
@include scrollbar-rail-hover($theme);
|
||||
> .ps-scrollbar-y {
|
||||
@include scrollbar-hover($theme);
|
||||
width: map_get($theme, scrollbar-y-hover-width);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,8 +43,8 @@
|
||||
|
||||
// Layout and theme mixin
|
||||
@mixin ps-container($theme) {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
-ms-touch-action: auto;
|
||||
touch-action: auto;
|
||||
overflow: hidden !important;
|
||||
-ms-overflow-style: none;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ var toInt = exports.toInt = function (x) {
|
||||
};
|
||||
|
||||
var clone = exports.clone = function (obj) {
|
||||
if (obj === null) {
|
||||
if (!obj) {
|
||||
return null;
|
||||
} else if (obj.constructor === Array) {
|
||||
return obj.map(clone);
|
||||
|
||||
@@ -6,7 +6,6 @@ module.exports = {
|
||||
minScrollbarLength: null,
|
||||
scrollXMarginOffset: 0,
|
||||
scrollYMarginOffset: 0,
|
||||
stopPropagationOnClick: true,
|
||||
suppressScrollX: false,
|
||||
suppressScrollY: false,
|
||||
swipePropagation: true,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
var _ = require('../../lib/helper');
|
||||
var instances = require('../instances');
|
||||
var updateGeometry = require('../update-geometry');
|
||||
var updateScroll = require('../update-scroll');
|
||||
@@ -11,43 +10,23 @@ function bindClickRailHandler(element, i) {
|
||||
}
|
||||
var stopPropagation = function (e) { e.stopPropagation(); };
|
||||
|
||||
if (i.settings.stopPropagationOnClick) {
|
||||
i.event.bind(i.scrollbarY, 'click', stopPropagation);
|
||||
}
|
||||
i.event.bind(i.scrollbarY, 'click', stopPropagation);
|
||||
i.event.bind(i.scrollbarYRail, 'click', function (e) {
|
||||
var halfOfScrollbarLength = _.toInt(i.scrollbarYHeight / 2);
|
||||
var positionTop = i.railYRatio * (e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top - halfOfScrollbarLength);
|
||||
var maxPositionTop = i.railYRatio * (i.railYHeight - i.scrollbarYHeight);
|
||||
var positionRatio = positionTop / maxPositionTop;
|
||||
var positionTop = e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top;
|
||||
var direction = positionTop > i.scrollbarYTop ? 1 : -1;
|
||||
|
||||
if (positionRatio < 0) {
|
||||
positionRatio = 0;
|
||||
} else if (positionRatio > 1) {
|
||||
positionRatio = 1;
|
||||
}
|
||||
|
||||
updateScroll(element, 'top', (i.contentHeight - i.containerHeight) * positionRatio);
|
||||
updateScroll(element, 'top', element.scrollTop + direction * i.containerHeight);
|
||||
updateGeometry(element);
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
if (i.settings.stopPropagationOnClick) {
|
||||
i.event.bind(i.scrollbarX, 'click', stopPropagation);
|
||||
}
|
||||
i.event.bind(i.scrollbarX, 'click', stopPropagation);
|
||||
i.event.bind(i.scrollbarXRail, 'click', function (e) {
|
||||
var halfOfScrollbarLength = _.toInt(i.scrollbarXWidth / 2);
|
||||
var positionLeft = i.railXRatio * (e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength);
|
||||
var maxPositionLeft = i.railXRatio * (i.railXWidth - i.scrollbarXWidth);
|
||||
var positionRatio = positionLeft / maxPositionLeft;
|
||||
var positionLeft = e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left;
|
||||
var direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
|
||||
|
||||
if (positionRatio < 0) {
|
||||
positionRatio = 0;
|
||||
} else if (positionRatio > 1) {
|
||||
positionRatio = 1;
|
||||
}
|
||||
|
||||
updateScroll(element, 'left', ((i.contentWidth - i.containerWidth) * positionRatio) - i.negativeScrollAdjustment);
|
||||
updateScroll(element, 'left', element.scrollLeft + direction * i.containerWidth);
|
||||
updateGeometry(element);
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -71,16 +71,40 @@ function bindKeyboardHandler(element, i) {
|
||||
|
||||
switch (e.which) {
|
||||
case 37: // left
|
||||
deltaX = -30;
|
||||
if (e.metaKey) {
|
||||
deltaX = -i.contentWidth;
|
||||
} else if (e.altKey) {
|
||||
deltaX = -i.containerWidth;
|
||||
} else {
|
||||
deltaX = -30;
|
||||
}
|
||||
break;
|
||||
case 38: // up
|
||||
deltaY = 30;
|
||||
if (e.metaKey) {
|
||||
deltaY = i.contentHeight;
|
||||
} else if (e.altKey) {
|
||||
deltaY = i.containerHeight;
|
||||
} else {
|
||||
deltaY = 30;
|
||||
}
|
||||
break;
|
||||
case 39: // right
|
||||
deltaX = 30;
|
||||
if (e.metaKey) {
|
||||
deltaX = i.contentWidth;
|
||||
} else if (e.altKey) {
|
||||
deltaX = i.containerWidth;
|
||||
} else {
|
||||
deltaX = 30;
|
||||
}
|
||||
break;
|
||||
case 40: // down
|
||||
deltaY = -30;
|
||||
if (e.metaKey) {
|
||||
deltaY = -i.contentHeight;
|
||||
} else if (e.altKey) {
|
||||
deltaY = -i.containerHeight;
|
||||
} else {
|
||||
deltaY = -30;
|
||||
}
|
||||
break;
|
||||
case 33: // page up
|
||||
deltaY = 90;
|
||||
|
||||
@@ -52,13 +52,18 @@ function bindMouseWheelHandler(element, i) {
|
||||
deltaY = e.wheelDelta;
|
||||
}
|
||||
|
||||
if (e.shiftKey) {
|
||||
// reverse axis with shift key
|
||||
return [-deltaY, -deltaX];
|
||||
}
|
||||
return [deltaX, deltaY];
|
||||
}
|
||||
|
||||
function shouldBeConsumedByChild(deltaX, deltaY) {
|
||||
var child = element.querySelector('textarea:hover, select[multiple]:hover, .ps-child:hover');
|
||||
if (child) {
|
||||
if (child.tagName !== 'TEXTAREA' && !window.getComputedStyle(child).overflow.match(/(scroll|auto)/)) {
|
||||
if (!window.getComputedStyle(child).overflow.match(/(scroll|auto)/)) {
|
||||
// if not scrollable
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,12 @@ function bindSelectionHandler(element, i) {
|
||||
stopScrolling();
|
||||
}
|
||||
});
|
||||
i.event.bind(window, 'keyup', function () {
|
||||
if (isSelected) {
|
||||
isSelected = false;
|
||||
stopScrolling();
|
||||
}
|
||||
});
|
||||
|
||||
i.event.bind(window, 'mousemove', function (e) {
|
||||
if (isSelected) {
|
||||
|
||||
@@ -128,6 +128,11 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!speed.x && !speed.y) {
|
||||
clearInterval(easingLoop);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
|
||||
clearInterval(easingLoop);
|
||||
return;
|
||||
|
||||
@@ -2,29 +2,14 @@
|
||||
|
||||
var instances = require('./instances');
|
||||
|
||||
var upEvent = document.createEvent('Event');
|
||||
var downEvent = document.createEvent('Event');
|
||||
var leftEvent = document.createEvent('Event');
|
||||
var rightEvent = document.createEvent('Event');
|
||||
var yEvent = document.createEvent('Event');
|
||||
var xEvent = document.createEvent('Event');
|
||||
var xStartEvent = document.createEvent('Event');
|
||||
var xEndEvent = document.createEvent('Event');
|
||||
var yStartEvent = document.createEvent('Event');
|
||||
var yEndEvent = document.createEvent('Event');
|
||||
var lastTop;
|
||||
var lastLeft;
|
||||
|
||||
upEvent.initEvent('ps-scroll-up', true, true);
|
||||
downEvent.initEvent('ps-scroll-down', true, true);
|
||||
leftEvent.initEvent('ps-scroll-left', true, true);
|
||||
rightEvent.initEvent('ps-scroll-right', true, true);
|
||||
yEvent.initEvent('ps-scroll-y', true, true);
|
||||
xEvent.initEvent('ps-scroll-x', true, true);
|
||||
xStartEvent.initEvent('ps-x-reach-start', true, true);
|
||||
xEndEvent.initEvent('ps-x-reach-end', true, true);
|
||||
yStartEvent.initEvent('ps-y-reach-start', true, true);
|
||||
yEndEvent.initEvent('ps-y-reach-end', true, true);
|
||||
var createDOMEvent = function (name) {
|
||||
var event = document.createEvent("Event");
|
||||
event.initEvent(name, true, true);
|
||||
return event;
|
||||
};
|
||||
|
||||
module.exports = function (element, axis, value) {
|
||||
if (typeof element === 'undefined') {
|
||||
@@ -41,12 +26,12 @@ module.exports = function (element, axis, value) {
|
||||
|
||||
if (axis === 'top' && value <= 0) {
|
||||
element.scrollTop = value = 0; // don't allow negative scroll
|
||||
element.dispatchEvent(yStartEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-y-reach-start'));
|
||||
}
|
||||
|
||||
if (axis === 'left' && value <= 0) {
|
||||
element.scrollLeft = value = 0; // don't allow negative scroll
|
||||
element.dispatchEvent(xStartEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-x-reach-start'));
|
||||
}
|
||||
|
||||
var i = instances.get(element);
|
||||
@@ -60,7 +45,7 @@ module.exports = function (element, axis, value) {
|
||||
} else {
|
||||
element.scrollTop = value;
|
||||
}
|
||||
element.dispatchEvent(yEndEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-y-reach-end'));
|
||||
}
|
||||
|
||||
if (axis === 'left' && value >= i.contentWidth - i.containerWidth) {
|
||||
@@ -72,7 +57,7 @@ module.exports = function (element, axis, value) {
|
||||
} else {
|
||||
element.scrollLeft = value;
|
||||
}
|
||||
element.dispatchEvent(xEndEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-x-reach-end'));
|
||||
}
|
||||
|
||||
if (!lastTop) {
|
||||
@@ -84,29 +69,29 @@ module.exports = function (element, axis, value) {
|
||||
}
|
||||
|
||||
if (axis === 'top' && value < lastTop) {
|
||||
element.dispatchEvent(upEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-up'));
|
||||
}
|
||||
|
||||
if (axis === 'top' && value > lastTop) {
|
||||
element.dispatchEvent(downEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-down'));
|
||||
}
|
||||
|
||||
if (axis === 'left' && value < lastLeft) {
|
||||
element.dispatchEvent(leftEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-left'));
|
||||
}
|
||||
|
||||
if (axis === 'left' && value > lastLeft) {
|
||||
element.dispatchEvent(rightEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-right'));
|
||||
}
|
||||
|
||||
if (axis === 'top') {
|
||||
element.scrollTop = lastTop = value;
|
||||
element.dispatchEvent(yEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-y'));
|
||||
}
|
||||
|
||||
if (axis === 'left') {
|
||||
element.scrollLeft = lastLeft = value;
|
||||
element.dispatchEvent(xEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-x'));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user