Compare commits

...

59 Commits

Author SHA1 Message Date
Hyunje Alex Jun
b959edbf78 Release 0.6.10
1. Add missing fix for touch/trackpad scrolling in IE10+ and Edge
2016-01-24 04:26:59 +09:00
Hyunje Alex Jun
c49cf7905e Re-apply missing IE10+ and Edge fix for touch/trackpad 2016-01-24 04:25:51 +09:00
Hyunje Alex Jun
f4cb31f8d8 Release 0.6.9
1. Add accessibility support with keyboard
2. Fix events not triggered when scrolling past boundaries
3. Fix touch/trackpad scrolling in IE10+ and Edge
4. Add theme feature
5. Remove transition and border-radius mixins from styles
2016-01-24 03:15:38 +09:00
Hyunje Alex Jun
965e315b30 Merge pull request #434 from wujekbogdan/Get-rid-of-border-radius-and-transition-mixins
replaced mixins with autoprefixer
2016-01-24 03:13:51 +09:00
DanielApt
3e76ce9d3e Merge branch 'pr/433' 2016-01-23 17:24:22 +00:00
Jun
2413028ad4 Merge pull request #401 from TheBoef/master
Touchpad/Trackpad scrolling IE10+ and Edge
2016-01-23 15:52:37 +09:00
Hyunje Alex Jun
cc0fded8cb 2015 -> 2016 and add LICENSE 2016-01-05 11:29:24 +09:00
Hyunje Alex Jun
fbfe505408 Remove comments from source files
Abundant comments.
2016-01-05 11:27:42 +09:00
Hyunje Alex Jun
c76aa08113 Update README.md
'#' is not a comment prefix in JavaScript. Use '//'.
2015-12-27 20:12:07 +09:00
DanielApt
4d7f441d1f Merge pull request #422 from axelboc/master
Fix events not triggered when scrolling past boundaries
2015-12-26 13:37:29 +01:00
Hyunje Alex Jun
4f6ed64b17 Make keyboard handler consistent when focused
Resolve #437
2015-12-23 23:34:37 +09:00
wujekbogdan
2fe45b3a97 typo fix. 2015-12-10 11:50:19 +01:00
wujekbogdan
57b1404e29 - removed transition() and border-radius() mixins
- added gulp-autoprefixer
2015-12-10 11:46:35 +01:00
wujekbogdan
bcfe954803 - fixed indentation (2 spaces)
- added missing new lines at the end of files
- removed 'ps-theme-big-and-ugly' theme
- improved readme.md. Added an example on how to create custom themes with scss.
2015-12-10 10:21:44 +01:00
Hyunje Alex Jun
31434f81d4 Release 0.6.8
1. Fix broken drag scrolling out of viewport
2. Fix untriggered scroll events
3. Remove select element hack for Firefox
4. Set scrollbar size to 0 when inactive
5. Add tabindex properties to scrollbars
2015-12-10 13:46:20 +09:00
Hyunje Alex Jun
8a3ed6d0b7 Add tabindex properties to scrollbars
Resolve #425
2015-12-10 13:36:19 +09:00
Hyunje Alex Jun
1dfbbe9e56 Set scrollbar size to 0 when inactive
Resolve #415
2015-12-10 13:17:59 +09:00
Hyunje Alex Jun
eb02d5ae65 Remove select element hack for Firefox
The select scrolling bug has been resolved in the latest version of
Firefox.

Resolve #311
2015-12-10 12:59:23 +09:00
wujekbogdan
6fbaa00403 no message 2015-12-09 22:08:57 +01:00
wujekbogdan
c14feba0bf added an example on how to create custom themes. 2015-12-09 22:08:48 +01:00
wujekbogdan
6fbfd5c90d updated README.md file. Added documentation for 'theme' parameter. 2015-12-09 22:01:10 +01:00
wujekbogdan
eddd2c2731 themeable perfect-scrollbar
- added „theme” parameter
- replaced all the CSS visual styles with SCSS variables
- added $ps-theme-default SCSS map that holds all the variables
- added $theme parameter to all the mixins
2015-12-09 18:19:02 +01:00
Axel Bocciarelli
c04b662a1b fix events not triggered when scrolling too past boundaries
Instead of returning when scrolling past the container's boundaries,
override `value` to the max allowed and let the other custom events
fire if needed.
2015-11-23 08:59:59 +11:00
Axel Bocciarelli
5ba86c2217 Merge remote-tracking branch 'noraesae/master' 2015-11-23 08:55:18 +11:00
DanielApt
6e32d3ddce Merge pull request #420 from axelboc/master
Dispatch custom events on `update` and fix scroll-end event not being triggered when dragging
2015-11-19 23:46:44 +00:00
Axel Bocciarelli
9f9f15f83c fix lint error 2015-11-19 11:50:31 +11:00
Axel Bocciarelli
7e04a2e72b trigger events on update
Dispatch the custom events on `Ps.update`:

```
container.scrollTop = 50;
Ps.update(container);
```

This is useful for controlling the scroll position via left/right
arrows and enabling/disabling these arrows on scroll or when the
start/end is reached. This also allows for the events to be dispatched
on page load by calling `Ps.update` right after `Ps.initialise`.
2015-11-19 11:26:28 +11:00
Axel Bocciarelli
24b34d3dea fix scroll-end events not triggered
... when dragging the scrollbar to the end with the mouse.
2015-11-19 11:05:57 +11:00
DanielApt
e1910cde3e use pageX/YOffset instead of scrollX/Y
As pointed out by @pliasetski these properties are not supported in IE11 and below

This fixes #409
2015-11-16 22:25:11 +00:00
DanielApt
bbf3d4db9f Remove usages of scrollbarYTop and scrollbarXLeft
#390
2015-11-10 22:41:56 +00:00
DanielApt
3b134d6193 Fix broken drag scrolling when left is out of viewport
Related to #390
2015-11-09 23:11:33 +00:00
DanielApt
e9024292cd Fix broken drag scrolling when top is out of viewport
Addresses issue no. 390 #390
2015-11-08 22:03:35 +00:00
TheBoef
e4dda6f408 Touchpad/Trackpad scrolling IE10+ and Edge
Right now you can't scroll with your touchpad/trackpad on a element that
has the perfect scrollbar in IE10+ and Edge.
By using the property '-ms-overflow-style' (Supported in IE10+ and Edge)
too hide the overflow instead of the default 'overflow' property, you
keep the scrolling with touchpad/trackpad functionality.
2015-10-14 23:59:19 +02:00
Hyunje Alex Jun
fd53ae0b48 Add a custom release NPM script. 2015-10-03 21:50:46 +09:00
Hyunje Alex Jun
66fd8bfd6a Release 0.6.7
Quick fix for 0.6.6.
2015-10-03 21:48:58 +09:00
Hyunje Alex Jun
4aa28add99 Add missing '.min' in compressed JS files 2015-10-03 21:48:02 +09:00
Hyunje Alex Jun
d6ede33202 Release 0.6.6
1. Add custom events
2. Support higher Node.js versions
3. Add useSelectionScroll option
4. Bug fixes
2015-10-03 21:44:26 +09:00
Hyunje Alex Jun
1c3b409d12 Remove 'bump' and 'release' tasks from gulpfile.js
There is only one JSON left for the project and it's better to bump the
version manually.
2015-10-03 21:43:59 +09:00
Hyunje Alex Jun
17e5f67519 Make selection scroll optional
It's not essential but rather causes several problems.
2015-10-03 21:37:24 +09:00
Hyunje Alex Jun
002034fd54 Return an Array object from class.list
To fix #383
2015-10-03 21:21:56 +09:00
Hyunje Alex Jun
8761735a54 Update Travis CI and NPM configuration
To be compatible with their newest versions.
2015-10-03 21:16:23 +09:00
Hyunje Alex Jun
c285521caa Lint update-scroll.js
With the new .eslintrc
2015-10-03 20:45:38 +09:00
Hyunje Alex Jun
3d2d50c308 Update .eslintrc
To make it compatible with new versions of ESLint and specify other
options.
2015-10-03 20:44:38 +09:00
DanielApt
a0d39e1b49 Make sure scroll is at the start/end when the reach start/end event fires 2015-09-29 15:28:58 +01:00
DanielApt
e288476ba0 Update README.md with new events 2015-09-28 11:13:25 +01:00
DanielApt
e9bc40bd37 Update events example to show new reach events 2015-09-28 11:09:51 +01:00
DanielApt
0b8fe0ac0b Dispatch events when reaching start / end of axes 2015-09-28 11:08:59 +01:00
Jun
a3676556b2 Merge pull request #386 from DanielApt/events
Dispatch scroll events
2015-09-24 19:44:31 +09:00
DanielApt
39893fc6f2 Add example for events 2015-09-24 11:02:33 +01:00
DanielApt
6c5b9d249e Add missing parentheses 2015-09-24 09:53:59 +01:00
DanielApt
2ef7e81ce9 Add Events to the README 2015-09-23 21:05:28 +01:00
DanielApt
3b90c734e4 Dispatch custom scroll events with new updateScroll function 2015-09-23 20:49:37 +01:00
Hyunje Alex Jun
afebe908b1 NPM version bump.
https://github.com/npm/npm-registry-couchapp/issues/148
2015-08-18 04:16:20 +09:00
Hyunje Alex Jun
6cbb4a9b9d Release 0.6.5
1. Add shift+space support.
2. Bug fixes.
2015-08-18 03:54:56 +09:00
Hyunje Alex Jun
51f33a44b5 Remove unused garbage rails before append a new one.
This patch fixes #376.
2015-08-18 03:51:12 +09:00
Hyunje Alex Jun
8eac54d49f Add a queryChildren method to dom.js 2015-08-18 03:26:15 +09:00
Hyunje Alex Jun
ed4e335978 Declare a module object DOM in dom.js
To refer in the sibling methods.
2015-08-18 03:23:27 +09:00
Jun
272bb4983a Merge pull request #379 from srcn/master
Add shift+space support for keyboard
2015-08-17 21:43:02 +09:00
srcn
f200bea4cc add shift+space support for keyboard 2015-08-17 15:19:30 +03:00
38 changed files with 722 additions and 405 deletions

View File

@@ -1,5 +1,5 @@
{
"env" : {
"env": {
"node": true,
"browser": true
},
@@ -7,14 +7,34 @@
"$": true,
"define": true
},
"rules" : {
"quotes": false,
"space-after-keywords": [2, "always", {"checkFunctionKeyword": true}],
"extends": "eslint:recommended",
"rules": {
"eqeqeq": 2,
"no-multi-spaces": 2,
"curly": 2,
"semi": 2,
"no-with": 2,
"strict": [2, "global"],
"radix": 2,
"no-use-before-define": 2,
"block-spacing": 2,
"brace-style": [2, "1tbs", {"allowSingleLine": true}],
"camelcase": 2,
"comma-spacing": [2, {"before": false, "after": true}],
"eol-last": 2,
"no-multiple-empty-lines": 2,
"indent": [2, 2],
"key-spacing": [2, {"beforeColon": false, "afterColon": true}],
"linebreak-style": [2, "unix"],
"new-parens": 2,
"no-trailing-spaces": 2,
"semi-spacing": 2,
"space-before-blocks": [2, "always"],
"brace-style": [2, "1tbs", { "allowSingleLine": false}],
"spaced-line-comment": [2, "always"],
"radix": [2, "always"],
"key-spacing": [2, "always", {"beforeColon": false, "afterColon": true}],
"no-multiple-empty-lines": [2, {max: 1}],
"space-before-function-paren": [2, {"anonymous": "always", "named": "never"}],
"space-in-parens": 2,
"space-infix-ops": 2,
"space-return-throw-case": 2,
"space-unary-ops": 2,
"spaced-comment": 2
}
}

View File

@@ -1,8 +1,7 @@
language: node_js
node_js:
- '0.10'
before_script:
- npm install -g gulp
- 0.12
- 4
deploy:
provider: releases
api_key:
@@ -13,5 +12,4 @@ deploy:
branch: master
tags: true
before_deploy:
- gulp
- gulp compress
- npm run before-deploy

19
LICENSE Normal file
View File

@@ -0,0 +1,19 @@
The MIT License (MIT) Copyright (c) 2016 Hyunje Alex Jun and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -218,10 +218,10 @@ require.config({
and load `perfectScrollbar` in the initialiser of your app:
```javascript
# for vanilla JS:
// for vanilla JS:
window.Ps = require('perfectScrollbar');
# for jQuery:
// for jQuery:
require('perfectScrollbarJQuery');
```
@@ -250,12 +250,12 @@ function (angular) {
And initialise perfectScrollbar in a controller:
```javascript
# by vanilla JS:
// by vanilla JS:
var container = document.getElementById('imgLoader');
Ps.initialize(container);
Ps.update(container);
# or by jQuery:
// or by jQuery:
var imgLoader = $("#imgLoader")
imgLoader.perfectScrollbar();
```
@@ -312,6 +312,87 @@ The number of pixels the content height can surpass the container height without
When set to false, when clicking on a rail, the click event will be allowed to propagate.
**Default: true**
### useSelectionScroll
When set to true, you can scroll the container by selecting text and move the cursor.
**Default: false**
### 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'**
**Example 1:**
Add `theme` parameter:
```javascript
Ps.initialize(container, {
theme: 'my-theme-name'
});
```
Create a class name prefixed with `.ps-theme-`. Include `ps-container()` mixin. It's recommended to use `map-merge()` to extend `$ps-theme-default` map with your custom styles.
```css#
.ps-theme-my-theme-name {
@include ps-container(map-merge($ps-theme-default, (
border-radius: 0,
scrollbar-x-rail-height: 20px,
scrollbar-x-height: 20px,
scrollbar-y-rail-width: 20px,
scrollbar-y-width: 20px,)
));
}
```
**Example 2:**
Alternatively, if you don't want to create your own themes, but only modify the default one, you could simply overwrite `$ps-*` variables with your own values. In this case `theme` parameter is not required when calling `.initialize()` method. Remember do define your own variables before the `theme.scss` file is imported.
## Events
perfect-scrollbar dispatches custom events.
### ps-scroll-y
This event fires when the y-axis is scrolled in either direction.
### ps-scroll-x
This event fires when the x-axis is scrolled in either direction.
### ps-scroll-up
This event fires when scrolling upwards.
### ps-scroll-down
This event fires when scrolling downwards.
### ps-scroll-left
This event fires when scrolling to the left.
### ps-scroll-right
This event fires when scrolling to the right.
### ps-y-reach-start
This event fires when scrolling reaches the start of the y-axis.
### ps-y-reach-end
This event fires when scrolling reaches the end of the y-axis (useful for infinite scroll).
### ps-x-reach-start
This event fires when scrolling reaches the start of the x-axis.
### ps-x-reach-end
This event fires when scrolling reaches the end of the x-axis.
You can listen to these events either with vanilla JavaScript
```javascript
document.addEventListener('ps-scroll-x', function () {
// ...
})
```
or with jQuery
```javascript
$(document).on('ps-scroll-x', function () {
// ...
})
```
## Contribution
#### Please read [Contributing](https://github.com/noraesae/perfect-scrollbar/wiki/Contributing) in the wiki before making any contribution.
@@ -345,7 +426,7 @@ For common problems there is a
## License
The MIT License (MIT) Copyright (c) 2015 Hyunje Alex Jun and other contributors.
The MIT License (MIT) Copyright (c) 2016 Hyunje Alex Jun and other contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@@ -0,0 +1,27 @@
<!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>
.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; }
</style>
</head>
<body>
<div id="Default" class="contentHolder">
<div class="content">
</div>
</div>
<script>
var $ = document.querySelector.bind(document);
window.onload = function () {
Ps.initialize($('#Default'), {
theme: 'big-and-ugly'
});
};
</script>
</body>
</html>

89
examples/events.html Normal file
View File

@@ -0,0 +1,89 @@
<!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>
p {
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;
}
</style>
</head>
<body>
<div class="container">
<div class="content">
</div>
</div>
<p><strong>Axis</strong> <span id="axis">&hellip;</span></p>
<p><strong>Direction</strong> <span id="direction">&hellip;</span></p>
<p><strong>Start / End</strong> <span id="start-end">(scroll to the start or end of an axis)</span></p>
<script>
var container = document.querySelector('.container')
, axis = document.getElementById('axis')
, direction = document.getElementById('direction')
, startEnd = document.getElementById('start-end');
Ps.initialize(container);
document.addEventListener('ps-scroll-y', function () {
axis.innerHTML = 'Y Axis';
});
document.addEventListener('ps-scroll-x', function () {
axis.innerHTML = 'X Axis';
});
document.addEventListener('ps-scroll-up', function () {
direction.innerHTML = 'up';
});
document.addEventListener('ps-scroll-down', function () {
direction.innerHTML = 'down';
});
document.addEventListener('ps-scroll-left', function () {
direction.innerHTML = 'left';
});
document.addEventListener('ps-scroll-right', function () {
direction.innerHTML = 'right';
});
document.addEventListener('ps-y-reach-start', function () {
startEnd.innerHTML = 'Reached start of <em>Y-Axis</em>';
});
document.addEventListener('ps-y-reach-end', function () {
startEnd.innerHTML = 'Reached end of <em>Y-Axis</em>';
});
document.addEventListener('ps-x-reach-start', function () {
startEnd.innerHTML = 'Reached start of <em>X-Axis</em>';
});
document.addEventListener('ps-x-reach-end', function () {
startEnd.innerHTML = 'Reached end of <em>X-Axis</em>'
});
</script>
</body>
</html>

View File

@@ -1,53 +0,0 @@
<!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>
#description {
border: 1px solid gray;
height:150px;
width: 400px;
overflow: auto;
position: relative;
}
#status { color: red; }
</style>
</head>
<body>
<div id="description" class="wrapper">
<p>Hello, world! 0</p>
<p>Hello, world! 1</p>
<p>Hello, world! 2</p>
<p>Hello, world! 3</p>
<p>Hello, world! 4</p>
<p>Hello, world! 5</p>
<p>Hello, world! 6</p>
<p>Hello, world! 7</p>
<p>Hello, world! 8</p>
<p>Hello, world! 9</p>
</div>
<div id="status">
</div>
<script type="text/javascript">
var $ = document.querySelector.bind(document);
window.onload = function () {
var container = $('#description');
var stat = $('#status');
Ps.initialize(container);
container.addEventListener('scroll', function (e) {
if(container.scrollTop === 0) {
stat.innerHTML = 'it reaches the top!';
}
else if (container.scrollTop === container.scrollHeight - container.clientHeight) {
stat.innerHTML = 'it reaches the end!';
} else {
stat.innerHTML = '';
}
});
};
</script>
</body>
</html>

View File

@@ -32,7 +32,9 @@
<script>
var $ = document.querySelector.bind(document);
window.onload = function () {
Ps.initialize($('#description'));
Ps.initialize($('#description'), {
useSelectionScroll: true
});
};
$('#redraw').addEventListener('click', function () {
var oldHtml = $('#description').innerHTML;

View File

@@ -2,15 +2,18 @@
var gulp = require('gulp')
, browserify = require('browserify')
, bump = require('gulp-bump')
, buffer = require('vinyl-buffer')
, connect = require('gulp-connect')
, del = require('del')
, eslint = require('gulp-eslint')
, insert = require('gulp-insert')
, path = require('path')
, rename = require('gulp-rename')
, rimraf = require('gulp-rimraf')
, sass = require('gulp-sass')
, transform = require('vinyl-transform')
, source = require('vinyl-source-stream')
, stream = require('event-stream')
, uglify = require('gulp-uglify')
, autoprefixer = require('gulp-autoprefixer')
, zip = require('gulp-zip');
var version = '/* perfect-scrollbar v' + require('./package').version + ' */\n';
@@ -23,98 +26,90 @@ gulp.task('lint', function () {
});
gulp.task('clean:js', function () {
return gulp.src('./dist/js/*.js', {read: false})
.pipe(rimraf());
return del(['./dist/js/*.js']);
});
gulp.task('clean:js:min', function () {
return gulp.src('./dist/js/min/*.js', {read: false})
.pipe(rimraf());
return del(['./dist/js/min/*.js']);
});
function browserified() {
return transform(function (filename) {
var b = browserify(filename);
return b.bundle();
});
}
var jsEntries = [
'./src/js/adaptor/global.js',
'./src/js/adaptor/jquery.js'
];
var autoPrefixerConfig = {
browsers: ['> 0%'], // '> 0%' forces autoprefixer to use all the possible prefixes. See https://github.com/ai/browserslist#queries for more details. IMO 'last 3 versions' would be good enough.
cascade: false
};
gulp.task('js', ['clean:js'], function () {
return gulp.src('./src/js/adaptor/*.js')
.pipe(browserified())
.pipe(insert.prepend(version))
.pipe(rename(function (path) {
if (path.basename === 'global') {
path.basename = 'perfect-scrollbar';
} else {
path.basename = 'perfect-scrollbar.' + path.basename;
}
}))
.pipe(gulp.dest('./dist/js'))
.pipe(connect.reload());
var tasks = jsEntries.map(function (src) {
return browserify([src]).bundle()
.pipe(source(path.basename(src)))
.pipe(buffer())
.pipe(insert.prepend(version))
.pipe(rename(function (path) {
if (path.basename === 'global') {
path.basename = 'perfect-scrollbar';
} else {
path.basename = 'perfect-scrollbar.' + path.basename;
}
}))
.pipe(gulp.dest('./dist/js'))
.pipe(connect.reload());
});
return stream.merge.apply(null, tasks);
});
gulp.task('js:min', ['clean:js:min'], function () {
return gulp.src('./src/js/adaptor/*.js')
.pipe(browserified())
.pipe(uglify())
.pipe(insert.prepend(version))
.pipe(rename(function (path) {
if (path.basename === 'global') {
path.basename = 'perfect-scrollbar.min';
} else {
path.basename = 'perfect-scrollbar.' + path.basename + '.min';
}
}))
.pipe(gulp.dest('./dist/js/min'));
var tasks = jsEntries.map(function (src) {
return browserify([src]).bundle()
.pipe(source(path.basename(src)))
.pipe(buffer())
.pipe(uglify())
.pipe(insert.prepend(version))
.pipe(rename(function (path) {
if (path.basename === 'global') {
path.basename = 'perfect-scrollbar.min';
} else {
path.basename = 'perfect-scrollbar.' + path.basename + '.min';
}
}))
.pipe(gulp.dest('./dist/js/min'))
.pipe(connect.reload());
});
return stream.merge.apply(null, tasks);
});
gulp.task('clean:css', function () {
return gulp.src('./dist/css/perfect-scrollbar.css', {read: false})
.pipe(rimraf());
return del(['./dist/css/perfect-scrollbar.css']);
});
gulp.task('clean:css:min', function () {
return gulp.src('./dist/css/perfect-scrollbar.min.css', {read: false})
.pipe(rimraf());
return del(['./dist/css/perfect-scrollbar.min.css']);
});
gulp.task('sass', ['clean:css'], function () {
gulp.task('css', ['clean:css'], function () {
return gulp.src('./src/css/main.scss')
.pipe(sass())
.pipe(autoprefixer(autoPrefixerConfig))
.pipe(insert.prepend(version))
.pipe(rename('perfect-scrollbar.css'))
.pipe(gulp.dest('./dist/css'))
.pipe(connect.reload());
});
gulp.task('sass:min', ['clean:css:min'], function () {
gulp.task('css:min', ['clean:css:min'], function () {
return gulp.src('./src/css/main.scss')
.pipe(sass({outputStyle: 'compressed'}))
.pipe(autoprefixer(autoPrefixerConfig))
.pipe(insert.prepend(version))
.pipe(rename('perfect-scrollbar.min.css'))
.pipe(gulp.dest('./dist/css'));
});
function bumpType() {
if (gulp.env.major) {
return 'major';
} else if (gulp.env.minor) {
return 'minor';
} else {
return 'patch';
}
}
gulp.task('bump', function () {
gulp.src('./*.json')
.pipe(bump({type: bumpType()}))
.pipe(gulp.dest('./'));
});
gulp.task('release', ['bump', 'build']);
gulp.task('build', ['js', 'js:min', 'sass', 'sass:min']);
gulp.task('build', ['js', 'js:min', 'css', 'css:min']);
gulp.task('connect', ['build'], function () {
connect.server({
@@ -125,7 +120,7 @@ gulp.task('connect', ['build'], function () {
gulp.task('watch', function () {
gulp.watch(['src/js/**/*'], ['js']);
gulp.watch(['src/css/**/*'], ['sass']);
gulp.watch(['src/css/**/*'], ['css']);
});
gulp.task('serve', ['connect', 'watch']);

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
module.exports = require('./src/js/main');

3
jquery.js vendored
View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
module.exports = require('./src/js/adaptor/jquery');

View File

@@ -1,6 +1,6 @@
{
"name": "perfect-scrollbar",
"version": "0.6.4",
"version": "0.6.10",
"description": "Minimalistic but perfect custom scrollbar plugin",
"author": "Hyunje Alex Jun <me@noraesae.net>",
"contributors": [
@@ -24,24 +24,28 @@
"scrollbar"
],
"engines": {
"node": ">= 0.8.0"
"node": ">= 0.12.0"
},
"devDependencies": {
"browserify": "^8.1.1",
"gulp": "^3.8.10",
"gulp-bump": "^0.1.11",
"browserify": "^11.2.0",
"del": "^2.0.2",
"event-stream": "^3.3.1",
"gulp": "^3.9.0",
"gulp-autoprefixer": "^3.1.0",
"gulp-connect": "^2.2.0",
"gulp-eslint": "^0.2.0",
"gulp-insert": "^0.4.0",
"gulp-rename": "^1.2.0",
"gulp-rimraf": "^0.1.1",
"gulp-sass": "^1.3.1",
"gulp-uglify": "^1.0.2",
"gulp-zip": "^2.0.2",
"vinyl-transform": "^1.0.0"
"gulp-eslint": "^1.0.0",
"gulp-insert": "^0.5.0",
"gulp-rename": "^1.2.2",
"gulp-sass": "^2.0.4",
"gulp-uglify": "^1.4.1",
"gulp-zip": "^3.0.2",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0"
},
"scripts": {
"test": "gulp"
"test": "gulp",
"before-deploy": "gulp && gulp compress",
"release": "rm -rf dist && gulp && npm publish"
},
"license": "MIT"
}

View File

@@ -1,123 +1,3 @@
// Colors
$ps-rail-hover: #eee;
$ps-bar-default: #aaa;
$ps-bar-hover: #999;
// Helper mixins
@mixin border-radius($r) {
-webkit-border-radius: $r;
-moz-border-radius: $r;
-ms-border-radius: $r;
border-radius: $r;
}
@mixin transition($t...) {
-webkit-transition: $t;
-moz-transition: $t;
-o-transition: $t;
transition: $t;
}
// Scrollbar mixins
@mixin scrollbar-rail-default {
display: none;
position: absolute; /* please don't change 'position' */
@include border-radius(4px);
opacity: 0;
@include transition(background-color .2s linear, opacity .2s linear);
}
@mixin scrollbar-rail-hover {
background-color: $ps-rail-hover;
opacity: 0.9;
}
@mixin scrollbar-default {
position: absolute; /* please don't change 'position' */
background-color: $ps-bar-default;
@include border-radius(4px);
@include transition(background-color .2s linear);
}
@mixin scrollbar-hover {
background-color: $ps-bar-hover;
}
@mixin in-scrolling {
&.ps-in-scrolling {
pointer-events: none;
&.ps-x>.ps-scrollbar-x-rail{
@include scrollbar-rail-hover;
>.ps-scrollbar-x {
@include scrollbar-hover;
}
}
&.ps-y>.ps-scrollbar-y-rail {
@include scrollbar-rail-hover;
>.ps-scrollbar-y {
@include scrollbar-hover;
}
}
}
}
.ps-container {
-ms-touch-action: none;
overflow: hidden !important;
&.ps-active-x > .ps-scrollbar-x-rail,
&.ps-active-y > .ps-scrollbar-y-rail {
display: block;
}
@include in-scrolling;
>.ps-scrollbar-x-rail {
@include scrollbar-rail-default;
bottom: 3px; /* there must be 'bottom' for ps-scrollbar-x-rail */
height: 8px;
>.ps-scrollbar-x {
@include scrollbar-default;
bottom: 0; /* there must be 'bottom' for ps-scrollbar-x */
height: 8px;
}
}
>.ps-scrollbar-y-rail {
@include scrollbar-rail-default;
right: 3px; /* there must be 'right' for ps-scrollbar-y-rail */
width: 8px;
>.ps-scrollbar-y {
@include scrollbar-default;
right: 0; /* there must be 'right' for ps-scrollbar-y */
width: 8px;
}
}
&:hover {
@include in-scrolling;
>.ps-scrollbar-x-rail,
>.ps-scrollbar-y-rail {
opacity: 0.6;
}
>.ps-scrollbar-x-rail:hover {
@include scrollbar-rail-hover;
>.ps-scrollbar-x {
@include scrollbar-hover;
}
}
>.ps-scrollbar-y-rail:hover {
@include scrollbar-rail-hover;
>.ps-scrollbar-y {
@include scrollbar-hover;
}
}
}
}
@import 'variables';
@import 'mixins';
@import 'themes';

115
src/css/mixins.scss Normal file
View File

@@ -0,0 +1,115 @@
@mixin scrollbar-rail-default($theme) {
display: none;
position: absolute; /* please don't change 'position' */
border-radius: map_get($theme, border-radius);
opacity: map_get($theme, rail-default-opacity);
transition: background-color .2s linear, opacity .2s linear;
}
@mixin scrollbar-rail-hover($theme) {
background-color: map_get($theme, rail-hover-bg);
opacity: map_get($theme, rail-hover-opacity);
}
@mixin scrollbar-default($theme) {
position: absolute; /* please don't change 'position' */
background-color: map_get($theme, bar-container-hover-bg);
border-radius: map_get($theme, border-radius);
transition: background-color .2s linear;
}
@mixin scrollbar-hover($theme) {
background-color: map_get($theme, bar-hover-bg);
}
@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);
}
}
&.ps-y > .ps-scrollbar-y-rail {
@include scrollbar-rail-hover($theme);
> .ps-scrollbar-y {
@include scrollbar-hover($theme);
}
}
}
}
// Layout and theme mixin
@mixin ps-container($theme) {
-ms-touch-action: none;
touch-action: none;
overflow: hidden !important;
-ms-overflow-style: none;
// Edge
@supports (-ms-overflow-style: none) {
overflow: auto !important;
}
// IE10+
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
overflow: auto !important;
}
&.ps-active-x > .ps-scrollbar-x-rail,
&.ps-active-y > .ps-scrollbar-y-rail {
display: block;
background-color: map_get($theme, bar-bg);
}
@include in-scrolling($theme);
> .ps-scrollbar-x-rail {
@include scrollbar-rail-default($theme);
bottom: map_get($theme, scrollbar-x-rail-bottom); /* there must be 'bottom' for ps-scrollbar-x-rail */
height: map_get($theme, scrollbar-x-rail-height);
> .ps-scrollbar-x {
@include scrollbar-default($theme);
bottom: map_get($theme, scrollbar-x-bottom); /* there must be 'bottom' for ps-scrollbar-x */
height: map_get($theme, scrollbar-x-height);
}
}
> .ps-scrollbar-y-rail {
@include scrollbar-rail-default($theme);
right: map_get($theme, scrollbar-y-rail-right); /* there must be 'right' for ps-scrollbar-y-rail */
width: map_get($theme, scrollbar-y-rail-width);
> .ps-scrollbar-y {
@include scrollbar-default($theme);
right: map_get($theme, scrollbar-y-right); /* there must be 'right' for ps-scrollbar-y */
width: map_get($theme, scrollbar-y-width);
}
}
&:hover {
@include in-scrolling($theme);
> .ps-scrollbar-x-rail,
> .ps-scrollbar-y-rail {
opacity: map_get($theme, rail-container-hover-opacity);
}
> .ps-scrollbar-x-rail:hover {
@include scrollbar-rail-hover($theme);
> .ps-scrollbar-x {
@include scrollbar-hover($theme);
}
}
> .ps-scrollbar-y-rail:hover {
@include scrollbar-rail-hover($theme);
> .ps-scrollbar-y {
@include scrollbar-hover($theme);
}
}
}
}

23
src/css/themes.scss Normal file
View File

@@ -0,0 +1,23 @@
$ps-theme-default: (
border-radius: $ps-border-radius,
rail-default-opacity: $ps-rail-default-opacity,
rail-container-hover-opacity: $ps-rail-container-hover-opacity,
rail-hover-opacity: $ps-rail-hover-opacity,
bar-bg: $ps-bar-bg,
bar-container-hover-bg: $ps-bar-container-hover-bg,
bar-hover-bg: $ps-bar-hover-bg,
rail-hover-bg: $ps-rail-hover-bg,
scrollbar-x-rail-bottom: $ps-scrollbar-x-rail-bottom,
scrollbar-x-rail-height: $ps-scrollbar-x-rail-height,
scrollbar-x-bottom: $ps-scrollbar-x-bottom,
scrollbar-x-height: $ps-scrollbar-x-height,
scrollbar-y-rail-right: $ps-scrollbar-y-rail-right,
scrollbar-y-rail-width: $ps-scrollbar-y-rail-width,
scrollbar-y-right: $ps-scrollbar-y-right,
scrollbar-y-width: $ps-scrollbar-y-width,
);
// Default theme
.ps-container {
@include ps-container($ps-theme-default);
}

22
src/css/variables.scss Normal file
View File

@@ -0,0 +1,22 @@
// Colors
$ps-border-radius: 4px !default;
$ps-rail-default-opacity: 0 !default;
$ps-rail-container-hover-opacity: 0.6 !default;
$ps-rail-hover-opacity: 0.9 !default;
$ps-bar-bg: transparent !default;
$ps-bar-container-hover-bg: #aaa !default;
$ps-bar-hover-bg: #999 !default;
$ps-rail-hover-bg: #eee !default;
// Sizes
$ps-scrollbar-x-rail-bottom: 3px !default;
$ps-scrollbar-x-rail-height: 8px !default;
$ps-scrollbar-x-bottom: 0 !default;
$ps-scrollbar-x-height: 8px !default;
$ps-scrollbar-y-rail-right: 3px !default;
$ps-scrollbar-y-rail-width: 8px !default;
$ps-scrollbar-y-right: 0 !default;
$ps-scrollbar-y-width: 8px !default;

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var ps = require('../main');

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var ps = require('../main')

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
function oldAdd(element, className) {
@@ -38,7 +35,7 @@ exports.remove = function (element, className) {
exports.list = function (element) {
if (element.classList) {
return element.classList;
return Array.prototype.slice.apply(element.classList);
} else {
return element.className.split(' ');
}

View File

@@ -1,15 +1,14 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
exports.e = function (tagName, className) {
var DOM = {};
DOM.e = function (tagName, className) {
var element = document.createElement(tagName);
element.className = className;
return element;
};
exports.appendTo = function (child, parent) {
DOM.appendTo = function (child, parent) {
parent.appendChild(child);
return child;
};
@@ -37,7 +36,7 @@ function cssMultiSet(element, obj) {
return element;
}
exports.css = function (element, styleNameOrObject, styleValue) {
DOM.css = function (element, styleNameOrObject, styleValue) {
if (typeof styleNameOrObject === 'object') {
// multiple set with object
return cssMultiSet(element, styleNameOrObject);
@@ -50,7 +49,7 @@ exports.css = function (element, styleNameOrObject, styleValue) {
}
};
exports.matches = function (element, query) {
DOM.matches = function (element, query) {
if (typeof element.matches !== 'undefined') {
return element.matches(query);
} else {
@@ -66,7 +65,7 @@ exports.matches = function (element, query) {
}
};
exports.remove = function (element) {
DOM.remove = function (element) {
if (typeof element.remove !== 'undefined') {
element.remove();
} else {
@@ -75,3 +74,11 @@ exports.remove = function (element) {
}
}
};
DOM.queryChildren = function (element, selector) {
return Array.prototype.filter.call(element.childNodes, function (child) {
return DOM.matches(child, selector);
});
};
module.exports = DOM;

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var EventElement = function (element) {

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
module.exports = (function () {

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var cls = require('./class')

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var destroy = require('./plugin/destroy')

View File

@@ -1,19 +1,18 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
module.exports = {
wheelSpeed: 1,
wheelPropagation: false,
swipePropagation: true,
minScrollbarLength: null,
maxScrollbarLength: null,
useBothWheelAxes: false,
useKeyboard: true,
suppressScrollX: false,
suppressScrollY: false,
minScrollbarLength: null,
scrollXMarginOffset: 0,
scrollYMarginOffset: 0,
stopPropagationOnClick: true
stopPropagationOnClick: true,
suppressScrollX: false,
suppressScrollY: false,
swipePropagation: true,
useBothWheelAxes: false,
useKeyboard: true,
useSelectionScroll: false,
wheelPropagation: false,
wheelSpeed: 1,
theme: 'default'
};

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var d = require('../lib/dom')

View File

@@ -1,11 +1,9 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var h = require('../../lib/helper')
, instances = require('../instances')
, updateGeometry = require('../update-geometry');
, updateGeometry = require('../update-geometry')
, updateScroll = require('../update-scroll');
function bindClickRailHandler(element, i) {
function pageOffset(el) {
@@ -18,7 +16,7 @@ function bindClickRailHandler(element, i) {
}
i.event.bind(i.scrollbarYRail, 'click', function (e) {
var halfOfScrollbarLength = h.toInt(i.scrollbarYHeight / 2);
var positionTop = i.railYRatio * (e.pageY - window.scrollY - pageOffset(i.scrollbarYRail).top - halfOfScrollbarLength);
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;
@@ -28,7 +26,7 @@ function bindClickRailHandler(element, i) {
positionRatio = 1;
}
element.scrollTop = (i.contentHeight - i.containerHeight) * positionRatio;
updateScroll(element, 'top', (i.contentHeight - i.containerHeight) * positionRatio);
updateGeometry(element);
e.stopPropagation();
@@ -39,7 +37,7 @@ function bindClickRailHandler(element, i) {
}
i.event.bind(i.scrollbarXRail, 'click', function (e) {
var halfOfScrollbarLength = h.toInt(i.scrollbarXWidth / 2);
var positionLeft = i.railXRatio * (e.pageX - window.scrollX - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength);
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;
@@ -49,7 +47,7 @@ function bindClickRailHandler(element, i) {
positionRatio = 1;
}
element.scrollLeft = ((i.contentWidth - i.containerWidth) * positionRatio) - i.negativeScrollAdjustment;
updateScroll(element, 'left', ((i.contentWidth - i.containerWidth) * positionRatio) - i.negativeScrollAdjustment);
updateGeometry(element);
e.stopPropagation();

View File

@@ -1,12 +1,10 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var d = require('../../lib/dom')
, h = require('../../lib/helper')
, instances = require('../instances')
, updateGeometry = require('../update-geometry');
, updateGeometry = require('../update-geometry')
, updateScroll = require('../update-scroll');
function bindMouseScrollXHandler(element, i) {
var currentLeft = null;
@@ -14,7 +12,7 @@ function bindMouseScrollXHandler(element, i) {
function updateScrollLeft(deltaX) {
var newLeft = currentLeft + (deltaX * i.railXRatio);
var maxLeft = i.scrollbarXRail.getBoundingClientRect().left + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
var maxLeft = Math.max(0, i.scrollbarXRail.getBoundingClientRect().left) + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
if (newLeft < 0) {
i.scrollbarXLeft = 0;
@@ -25,7 +23,7 @@ function bindMouseScrollXHandler(element, i) {
}
var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
element.scrollLeft = scrollLeft;
updateScroll(element, 'left', scrollLeft);
}
var mouseMoveHandler = function (e) {
@@ -59,7 +57,7 @@ function bindMouseScrollYHandler(element, i) {
function updateScrollTop(deltaY) {
var newTop = currentTop + (deltaY * i.railYRatio);
var maxTop = i.scrollbarYRail.getBoundingClientRect().top + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
var maxTop = Math.max(0, i.scrollbarYRail.getBoundingClientRect().top) + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
if (newTop < 0) {
i.scrollbarYTop = 0;
@@ -70,7 +68,7 @@ function bindMouseScrollYHandler(element, i) {
}
var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
element.scrollTop = scrollTop;
updateScroll(element, 'top', scrollTop);
}
var mouseMoveHandler = function (e) {

View File

@@ -1,11 +1,10 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var h = require('../../lib/helper')
, d = require('../../lib/dom')
, instances = require('../instances')
, updateGeometry = require('../update-geometry');
, updateGeometry = require('../update-geometry')
, updateScroll = require('../update-scroll');
function bindKeyboardHandler(element, i) {
var hovered = false;
@@ -45,7 +44,10 @@ function bindKeyboardHandler(element, i) {
return;
}
if (!hovered) {
var focused = d.matches(i.scrollbarX, ':focus') ||
d.matches(i.scrollbarY, ':focus');
if (!hovered && !focused) {
return;
}
@@ -80,6 +82,12 @@ function bindKeyboardHandler(element, i) {
deltaY = 90;
break;
case 32: // space bar
if (e.shiftKey) {
deltaY = 90;
} else {
deltaY = -90;
}
break;
case 34: // page down
deltaY = -90;
break;
@@ -101,8 +109,8 @@ function bindKeyboardHandler(element, i) {
return;
}
element.scrollTop = element.scrollTop - deltaY;
element.scrollLeft = element.scrollLeft + deltaX;
updateScroll(element, 'top', element.scrollTop - deltaY);
updateScroll(element, 'left', element.scrollLeft + deltaX);
updateGeometry(element);
shouldPrevent = shouldPreventDefault(deltaX, deltaY);

View File

@@ -1,11 +1,8 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var h = require('../../lib/helper')
, instances = require('../instances')
, updateGeometry = require('../update-geometry');
var instances = require('../instances')
, updateGeometry = require('../update-geometry')
, updateScroll = require('../update-scroll');
function bindMouseWheelHandler(element, i) {
var shouldPrevent = false;
@@ -80,13 +77,6 @@ function bindMouseWheelHandler(element, i) {
}
function mousewheelHandler(e) {
// FIXME: this is a quick fix for the select problem in FF and IE.
// If there comes an effective way to deal with the problem,
// this lines should be removed.
if (!h.env.isWebKit && element.querySelector('select:focus')) {
return;
}
var delta = getDeltaFromEvent(e);
var deltaX = delta[0];
@@ -100,24 +90,24 @@ function bindMouseWheelHandler(element, i) {
if (!i.settings.useBothWheelAxes) {
// deltaX will only be used for horizontal scrolling and deltaY will
// only be used for vertical scrolling - this is the default
element.scrollTop = element.scrollTop - (deltaY * i.settings.wheelSpeed);
element.scrollLeft = element.scrollLeft + (deltaX * i.settings.wheelSpeed);
updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
} else if (i.scrollbarYActive && !i.scrollbarXActive) {
// only vertical scrollbar is active and useBothWheelAxes option is
// active, so let's scroll vertical bar using both mouse wheel axes
if (deltaY) {
element.scrollTop = element.scrollTop - (deltaY * i.settings.wheelSpeed);
updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
} else {
element.scrollTop = element.scrollTop + (deltaX * i.settings.wheelSpeed);
updateScroll(element, 'top', element.scrollTop + (deltaX * i.settings.wheelSpeed));
}
shouldPrevent = true;
} else if (i.scrollbarXActive && !i.scrollbarYActive) {
// useBothWheelAxes and only horizontal bar is active, so use both
// wheel axes for horizontal bar
if (deltaX) {
element.scrollLeft = element.scrollLeft + (deltaX * i.settings.wheelSpeed);
updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
} else {
element.scrollLeft = element.scrollLeft - (deltaY * i.settings.wheelSpeed);
updateScroll(element, 'left', element.scrollLeft - (deltaY * i.settings.wheelSpeed));
}
shouldPrevent = true;
}

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var instances = require('../instances')

View File

@@ -1,11 +1,9 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var h = require('../../lib/helper')
, instances = require('../instances')
, updateGeometry = require('../update-geometry');
, updateGeometry = require('../update-geometry')
, updateScroll = require('../update-scroll');
function bindSelectionHandler(element, i) {
function getRangeNode() {
@@ -28,8 +26,8 @@ function bindSelectionHandler(element, i) {
return;
}
element.scrollTop = element.scrollTop + scrollDiff.top;
element.scrollLeft = element.scrollLeft + scrollDiff.left;
updateScroll(element, 'top', element.scrollTop + scrollDiff.top);
updateScroll(element, 'left', element.scrollLeft + scrollDiff.left);
updateGeometry(element);
}, 50); // every .1 sec
}

View File

@@ -1,10 +1,8 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var instances = require('../instances')
, updateGeometry = require('../update-geometry');
, updateGeometry = require('../update-geometry')
, updateScroll = require('../update-scroll');
function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
function shouldPreventDefault(deltaX, deltaY) {
@@ -33,8 +31,8 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
}
function applyTouchMove(differenceX, differenceY) {
element.scrollTop = element.scrollTop - differenceY;
element.scrollLeft = element.scrollLeft - differenceX;
updateScroll(element, 'top', element.scrollTop - differenceY);
updateScroll(element, 'left', element.scrollLeft - differenceX);
updateGeometry(element);
}

View File

@@ -1,6 +1,3 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var cls = require('../lib/class')
@@ -26,12 +23,16 @@ module.exports = function (element, userSettings) {
var i = instances.add(element);
i.settings = h.extend(i.settings, userSettings);
cls.add(element, 'ps-theme-' + i.settings.theme);
clickRailHandler(element);
dragScrollbarHandler(element);
mouseWheelHandler(element);
nativeScrollHandler(element);
selectionHandler(element);
if (i.settings.useSelectionScroll) {
selectionHandler(element);
}
if (h.env.supportsTouch || h.env.supportsIePointer) {
touchHandler(element, h.env.supportsTouch, h.env.supportsIePointer);

View File

@@ -1,9 +1,7 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var d = require('../lib/dom')
var cls = require('../lib/class')
, d = require('../lib/dom')
, defaultSettings = require('./default-setting')
, EventManager = require('../lib/event-manager')
, guid = require('../lib/guid')
@@ -33,8 +31,19 @@ function Instance(element) {
i.event = new EventManager();
i.ownerDocument = element.ownerDocument || document;
function focus() {
cls.add(element, 'ps-focus');
}
function blur() {
cls.remove(element, 'ps-focus');
}
i.scrollbarXRail = d.appendTo(d.e('div', 'ps-scrollbar-x-rail'), element);
i.scrollbarX = d.appendTo(d.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
i.scrollbarX.setAttribute('tabindex', 0);
i.event.bind(i.scrollbarX, 'focus', focus);
i.event.bind(i.scrollbarX, 'blur', blur);
i.scrollbarXActive = null;
i.scrollbarXWidth = null;
i.scrollbarXLeft = null;
@@ -51,6 +60,9 @@ function Instance(element) {
i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element);
i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
i.scrollbarY.setAttribute('tabindex', 0);
i.event.bind(i.scrollbarY, 'focus', focus);
i.event.bind(i.scrollbarY, 'blur', blur);
i.scrollbarYActive = null;
i.scrollbarYHeight = null;
i.scrollbarYTop = null;

View File

@@ -1,12 +1,10 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var cls = require('../lib/class')
, d = require('../lib/dom')
, h = require('../lib/helper')
, instances = require('./instances');
, instances = require('./instances')
, updateScroll = require('./update-scroll');
function getThumbSize(i, thumbSize) {
if (i.settings.minScrollbarLength) {
@@ -60,10 +58,23 @@ module.exports = function (element) {
i.contentWidth = element.scrollWidth;
i.contentHeight = element.scrollHeight;
var existingRails;
if (!element.contains(i.scrollbarXRail)) {
existingRails = d.queryChildren(element, '.ps-scrollbar-x-rail');
if (existingRails.length > 0) {
existingRails.forEach(function (rail) {
d.remove(rail);
});
}
d.appendTo(i.scrollbarXRail, element);
}
if (!element.contains(i.scrollbarYRail)) {
existingRails = d.queryChildren(element, '.ps-scrollbar-y-rail');
if (existingRails.length > 0) {
existingRails.forEach(function (rail) {
d.remove(rail);
});
}
d.appendTo(i.scrollbarYRail, element);
}
@@ -75,9 +86,6 @@ module.exports = function (element) {
i.scrollbarXLeft = h.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
} else {
i.scrollbarXActive = false;
i.scrollbarXWidth = 0;
i.scrollbarXLeft = 0;
element.scrollLeft = 0;
}
if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) {
@@ -88,9 +96,6 @@ module.exports = function (element) {
i.scrollbarYTop = h.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight));
} else {
i.scrollbarYActive = false;
i.scrollbarYHeight = 0;
i.scrollbarYTop = 0;
element.scrollTop = 0;
}
if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
@@ -102,6 +107,20 @@ module.exports = function (element) {
updateCss(element, i);
cls[i.scrollbarXActive ? 'add' : 'remove'](element, 'ps-active-x');
cls[i.scrollbarYActive ? 'add' : 'remove'](element, 'ps-active-y');
if (i.scrollbarXActive) {
cls.add(element, 'ps-active-x');
} else {
cls.remove(element, 'ps-active-x');
i.scrollbarXWidth = 0;
i.scrollbarXLeft = 0;
updateScroll(element, 'left', 0);
}
if (i.scrollbarYActive) {
cls.add(element, 'ps-active-y');
} else {
cls.remove(element, 'ps-active-y');
i.scrollbarYHeight = 0;
i.scrollbarYTop = 0;
updateScroll(element, 'top', 0);
}
};

View File

@@ -0,0 +1,98 @@
'use strict';
var instances = require('./instances');
var upEvent = document.createEvent('Event')
, downEvent = document.createEvent('Event')
, leftEvent = document.createEvent('Event')
, rightEvent = document.createEvent('Event')
, yEvent = document.createEvent('Event')
, xEvent = document.createEvent('Event')
, xStartEvent = document.createEvent('Event')
, xEndEvent = document.createEvent('Event')
, yStartEvent = document.createEvent('Event')
, yEndEvent = document.createEvent('Event')
, lastTop
, 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);
module.exports = function (element, axis, value) {
if (typeof element === 'undefined') {
throw 'You must provide an element to the update-scroll function';
}
if (typeof axis === 'undefined') {
throw 'You must provide an axis to the update-scroll function';
}
if (typeof value === 'undefined') {
throw 'You must provide a value to the update-scroll function';
}
if (axis === 'top' && value <= 0) {
element.scrollTop = value = 0; // don't allow negative scroll
element.dispatchEvent(yStartEvent);
}
if (axis === 'left' && value <= 0) {
element.scrollLeft = value = 0; // don't allow negative scroll
element.dispatchEvent(xStartEvent);
}
var i = instances.get(element);
if (axis === 'top' && value >= i.contentHeight - i.containerHeight) {
element.scrollTop = value = i.contentHeight - i.containerHeight; // don't allow scroll past container
element.dispatchEvent(yEndEvent);
}
if (axis === 'left' && value >= i.contentWidth - i.containerWidth) {
element.scrollLeft = value = i.contentWidth - i.containerWidth; // don't allow scroll past container
element.dispatchEvent(xEndEvent);
}
if (!lastTop) {
lastTop = element.scrollTop;
}
if (!lastLeft) {
lastLeft = element.scrollLeft;
}
if (axis === 'top' && value < lastTop) {
element.dispatchEvent(upEvent);
}
if (axis === 'top' && value > lastTop) {
element.dispatchEvent(downEvent);
}
if (axis === 'left' && value < lastLeft) {
element.dispatchEvent(leftEvent);
}
if (axis === 'left' && value > lastLeft) {
element.dispatchEvent(rightEvent);
}
if (axis === 'top') {
element.scrollTop = lastTop = value;
element.dispatchEvent(yEvent);
}
if (axis === 'left') {
element.scrollLeft = lastLeft = value;
element.dispatchEvent(xEvent);
}
};

View File

@@ -1,12 +1,10 @@
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
'use strict';
var d = require('../lib/dom')
, h = require('../lib/helper')
, instances = require('./instances')
, updateGeometry = require('./update-geometry');
, updateGeometry = require('./update-geometry')
, updateScroll = require('./update-scroll');
module.exports = function (element) {
var i = instances.get(element);
@@ -30,6 +28,10 @@ module.exports = function (element) {
updateGeometry(element);
// Update top/left scroll to trigger events
updateScroll(element, 'top', element.scrollTop);
updateScroll(element, 'left', element.scrollLeft);
d.css(i.scrollbarXRail, 'display', '');
d.css(i.scrollbarYRail, 'display', '');
};