Compare commits

...

23 Commits

Author SHA1 Message Date
Hyunje Jun
25e5be13ff Release 0.6.14
1. Include TypeScript definition
2016-11-04 16:31:23 +09:00
Hyunje Jun
f683b01959 Include TypeScript definition in published files 2016-11-04 16:30:33 +09:00
Hyunje Jun
6d2f203441 Release 0.6.13
1. Add meta and alt key handling in keyboard scrolling - #549
2. Implement reverse wheel axis on shift key - #548
3. Add TypeScript definition - #552
4. Fix click propagation on scrollbar thumbs - #526 #547
5. Implement correct click-rail handler - #568
6. Minor bug fixes
2016-10-18 16:51:59 +09:00
Hyunje Jun
a4808f662e Implement right click-rail handler
Resolve #568.
2016-10-18 16:50:52 +09:00
Hyunje Jun
98fa15167a Remove 'stopPropagationOnClick'
It was wrong fix.
2016-10-18 16:38:13 +09:00
Hyunje Jun
06929ae685 Don't consume if child's not scrollable
Resolve #541.
2016-10-18 16:28:52 +09:00
Hyunje Jun
aa63ff0370 Disable selection scroll on key pressed
Resolve #570.
2016-10-18 16:01:03 +09:00
Hyunje Jun
c7ddde69c2 Add example to change theme 2016-10-18 15:45:19 +09:00
Hyunje Jun
69e3fb2688 Apply hover style for drag scrolling
Resolve #555.
2016-10-18 14:59:27 +09:00
Hyunje Jun
fad7f8b4a6 Add TypeScript definition
Resolve #552.
2016-10-18 12:58:42 +09:00
Hyunje Jun
0deb4c9bc7 Don't use pointer-events: none
Resolve #526 and #547.
2016-10-18 12:45:58 +09:00
Hyunje Jun
11fcd09a99 Reverse wheel scroll axis on shift pressed
Resolve #548.
2016-10-18 11:55:03 +09:00
Hyunje Jun
0fc5c69b3f Add metaKey and altKey handling in keyboard handler
Resolve #549.
2016-10-18 11:49:20 +09:00
Hyunje Jun
898928b686 Don't do type-safe comparison on null
Resolve #537.
2016-10-18 11:00:22 +09:00
Hyunje Jun
ce7146121f Set touch-action to auto
Resolve #480.
2016-10-18 10:18:55 +09:00
Jun
908cee5490 Merge pull request #535 from lpetrov/invalid-state-error-on-scroll-update
Fixes https://github.com/noraesae/perfect-scrollbar/issues/534 (Calli…
2016-08-13 12:55:29 +09:00
Jun
b3880ca638 Merge pull request #551 from maximeloizeau/touch-scrolling-bug
Touch scrolling bug
2016-08-12 08:58:42 +09:00
Maxime Loizeau
7123891d4d Updated code styling to match repo recommendations 2016-08-11 15:55:20 +01:00
Maxime Loizeau
4c00a7fdb9 Prevent infinite update when touching without moving 2016-08-11 15:50:46 +01:00
Jun
3719dd614c Merge pull request #536 from frg/jspm-dependencies
Defined dependencies for jspm
2016-07-27 18:56:35 +09:00
Jean Farrugia
68dbc427ea added jspm dependencies 2016-07-20 07:47:22 +02:00
Lyubomir Petrov
34135d6ef0 Fixes https://github.com/noraesae/perfect-scrollbar/issues/534 (Calling .update from an ps-scroll-y triggers an InvalidStateError #534) 2016-07-19 15:57:17 +03:00
Jun
0ab95f2d57 Drop TravisCI testing on Node 0.12 2016-07-13 02:33:53 +09:00
15 changed files with 190 additions and 80 deletions

View File

@@ -1,6 +1,5 @@
language: node_js
node_js:
- 0.12
- 4
deploy:
provider: releases

View File

@@ -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'`

View File

@@ -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>

View 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>

View File

@@ -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
View 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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -6,7 +6,6 @@ module.exports = {
minScrollbarLength: null,
scrollXMarginOffset: 0,
scrollYMarginOffset: 0,
stopPropagationOnClick: true,
suppressScrollX: false,
suppressScrollY: false,
swipePropagation: true,

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;

View File

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