Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66fd8bfd6a | ||
|
|
4aa28add99 | ||
|
|
d6ede33202 | ||
|
|
1c3b409d12 | ||
|
|
17e5f67519 | ||
|
|
002034fd54 | ||
|
|
8761735a54 | ||
|
|
c285521caa | ||
|
|
3d2d50c308 | ||
|
|
a0d39e1b49 | ||
|
|
e288476ba0 | ||
|
|
e9bc40bd37 | ||
|
|
0b8fe0ac0b | ||
|
|
a3676556b2 | ||
|
|
39893fc6f2 | ||
|
|
6c5b9d249e | ||
|
|
2ef7e81ce9 | ||
|
|
3b90c734e4 | ||
|
|
afebe908b1 | ||
|
|
6cbb4a9b9d | ||
|
|
51f33a44b5 | ||
|
|
8eac54d49f | ||
|
|
ed4e335978 | ||
|
|
272bb4983a | ||
|
|
f200bea4cc | ||
|
|
b1d7aa0e64 | ||
|
|
49e39f513d | ||
|
|
89f4226778 | ||
|
|
79f4cfcf5f | ||
|
|
158b113d18 | ||
|
|
6c642d8a47 | ||
|
|
f9f20eeb6f | ||
|
|
1f082a2e04 | ||
|
|
b19c5e0765 | ||
|
|
3dbf20a5d0 | ||
|
|
db855ceca1 | ||
|
|
84b74926e3 | ||
|
|
d6bd30f2da | ||
|
|
fc28ceb4ea | ||
|
|
ca4d835129 | ||
|
|
88b4e2fc19 | ||
|
|
de32082a62 | ||
|
|
7ba25d020c | ||
|
|
08d559561e | ||
|
|
046ce954fd | ||
|
|
a40ab40695 |
14
.editorconfig
Normal file
14
.editorconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
# EditorConfig: http://editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# Indentation for JS & SCSS
|
||||
[*.{js, scss}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
38
.eslintrc
38
.eslintrc
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
.idea
|
||||
.idea
|
||||
|
||||
@@ -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
|
||||
|
||||
116
README.md
116
README.md
@@ -46,6 +46,7 @@ I hope you love it!
|
||||
to update the size or position of the scrollbar, just update.
|
||||
* Additionally, perfect-scrollbar uses 'scrollTop' and 'scrollLeft',
|
||||
not absolute positioning or something messy.
|
||||
* perfect-scrollbar supports RTL perfectly on both WebKit and Gecko based browsers.
|
||||
|
||||
It's cool, isn't it?
|
||||
|
||||
@@ -199,6 +200,66 @@ $('#container').perfectScrollbar('update'); // Update
|
||||
$('#container').perfectScrollbar('destroy'); // Destroy
|
||||
```
|
||||
|
||||
## RequireJS usage
|
||||
|
||||
For RequireJS loader, no need to write shim, simply import two libs:
|
||||
|
||||
```javascript
|
||||
require.config({
|
||||
paths: {
|
||||
perfectScrollbarJQuery: '.../perfect-scrollbar.jquery',
|
||||
perfectScrollbar: '.../perfect-scrollbar',
|
||||
}
|
||||
...
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
and load `perfectScrollbar` in the initialiser of your app:
|
||||
|
||||
```javascript
|
||||
# for vanilla JS:
|
||||
window.Ps = require('perfectScrollbar');
|
||||
|
||||
# for jQuery:
|
||||
require('perfectScrollbarJQuery');
|
||||
```
|
||||
|
||||
|
||||
## AngularJS + RequireJS usage
|
||||
|
||||
With the require.config settings above, at the beginning of your app module
|
||||
definition, you can have following code:
|
||||
|
||||
```javascript
|
||||
define([
|
||||
'angular',
|
||||
'perfectScrollbar',
|
||||
'perfectScrollbarJquery'
|
||||
],
|
||||
function (angular) {
|
||||
var myApp = angular.module('myApp', [])
|
||||
.run(function() {
|
||||
window.Ps = require('perfectScrollbar');
|
||||
require('perfectScrollbarJQuery');
|
||||
})
|
||||
return myApp;
|
||||
});
|
||||
```
|
||||
|
||||
And initialise perfectScrollbar in a controller:
|
||||
|
||||
```javascript
|
||||
# by vanilla JS:
|
||||
var container = document.getElementById('imgLoader');
|
||||
Ps.initialize(container);
|
||||
Ps.update(container);
|
||||
|
||||
# or by jQuery:
|
||||
var imgLoader = $("#imgLoader")
|
||||
imgLoader.perfectScrollbar();
|
||||
```
|
||||
|
||||
## Optional parameters
|
||||
|
||||
perfect-scrollbar supports optional parameters.
|
||||
@@ -247,6 +308,61 @@ 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**
|
||||
|
||||
### useSelectionScroll
|
||||
When set to true, you can scroll the container by selecting text and move the cursor.
|
||||
**Default: false**
|
||||
|
||||
## 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.
|
||||
|
||||
89
examples/events.html
Normal file
89
examples/events.html
Normal 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">…</span></p>
|
||||
|
||||
<p><strong>Direction</strong> <span id="direction">…</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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
111
gulpfile.js
111
gulpfile.js
@@ -2,14 +2,16 @@
|
||||
|
||||
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')
|
||||
, zip = require('gulp-zip');
|
||||
|
||||
@@ -23,63 +25,66 @@ 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'
|
||||
];
|
||||
|
||||
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(insert.prepend(version))
|
||||
@@ -88,7 +93,7 @@ gulp.task('sass', ['clean:css'], function () {
|
||||
.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(insert.prepend(version))
|
||||
@@ -96,25 +101,7 @@ gulp.task('sass:min', ['clean:css:min'], function () {
|
||||
.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({
|
||||
|
||||
30
package.json
30
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "perfect-scrollbar",
|
||||
"version": "0.6.2",
|
||||
"version": "0.6.7",
|
||||
"description": "Minimalistic but perfect custom scrollbar plugin",
|
||||
"author": "Hyunje Alex Jun <me@noraesae.net>",
|
||||
"contributors": [
|
||||
@@ -24,24 +24,26 @@
|
||||
"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-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"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ $ps-bar-hover: #999;
|
||||
}
|
||||
|
||||
.ps-container {
|
||||
-ms-touch-action: none;
|
||||
overflow: hidden !important;
|
||||
|
||||
&.ps-active-x > .ps-scrollbar-x-rail,
|
||||
|
||||
@@ -38,7 +38,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(' ');
|
||||
}
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
*/
|
||||
'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 +39,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 +52,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 +68,7 @@ exports.matches = function (element, query) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.remove = function (element) {
|
||||
DOM.remove = function (element) {
|
||||
if (typeof element.remove !== 'undefined') {
|
||||
element.remove();
|
||||
} else {
|
||||
@@ -75,3 +77,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;
|
||||
|
||||
@@ -7,11 +7,7 @@ var cls = require('./class')
|
||||
, d = require('./dom');
|
||||
|
||||
exports.toInt = function (x) {
|
||||
if (typeof x === 'string') {
|
||||
return parseInt(x, 10);
|
||||
} else {
|
||||
return ~~x;
|
||||
}
|
||||
return parseInt(x, 10) || 0;
|
||||
};
|
||||
|
||||
exports.clone = function (obj) {
|
||||
|
||||
@@ -4,15 +4,17 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
wheelSpeed: 1,
|
||||
wheelPropagation: false,
|
||||
swipePropagation: true,
|
||||
minScrollbarLength: null,
|
||||
maxScrollbarLength: null,
|
||||
useBothWheelAxes: false,
|
||||
useKeyboard: true,
|
||||
minScrollbarLength: null,
|
||||
scrollXMarginOffset: 0,
|
||||
scrollYMarginOffset: 0,
|
||||
stopPropagationOnClick: true,
|
||||
suppressScrollX: false,
|
||||
suppressScrollY: false,
|
||||
scrollXMarginOffset: 0,
|
||||
scrollYMarginOffset: 0
|
||||
swipePropagation: true,
|
||||
useBothWheelAxes: false,
|
||||
useKeyboard: true,
|
||||
useSelectionScroll: false,
|
||||
wheelPropagation: false,
|
||||
wheelSpeed: 1
|
||||
};
|
||||
|
||||
@@ -10,6 +10,10 @@ var d = require('../lib/dom')
|
||||
module.exports = function (element) {
|
||||
var i = instances.get(element);
|
||||
|
||||
if (!i) {
|
||||
return;
|
||||
}
|
||||
|
||||
i.event.unbindAll();
|
||||
d.remove(i.scrollbarX);
|
||||
d.remove(i.scrollbarY);
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
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) {
|
||||
@@ -13,11 +14,13 @@ function bindClickRailHandler(element, i) {
|
||||
}
|
||||
var stopPropagation = window.Event.prototype.stopPropagation.bind;
|
||||
|
||||
i.event.bind(i.scrollbarY, 'click', stopPropagation);
|
||||
if (i.settings.stopPropagationOnClick) {
|
||||
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) {
|
||||
@@ -26,16 +29,19 @@ 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();
|
||||
});
|
||||
|
||||
i.event.bind(i.scrollbarX, 'click', stopPropagation);
|
||||
if (i.settings.stopPropagationOnClick) {
|
||||
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) {
|
||||
@@ -44,8 +50,10 @@ function bindClickRailHandler(element, i) {
|
||||
positionRatio = 1;
|
||||
}
|
||||
|
||||
element.scrollLeft = (i.contentWidth - i.containerWidth) * positionRatio;
|
||||
updateScroll(element, 'left', ((i.contentWidth - i.containerWidth) * positionRatio) - i.negativeScrollAdjustment);
|
||||
updateGeometry(element);
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,16 @@
|
||||
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;
|
||||
var currentPageX = null;
|
||||
|
||||
function updateScrollLeft(deltaX) {
|
||||
var newLeft = currentLeft + deltaX;
|
||||
var maxLeft = i.containerWidth - i.scrollbarXWidth;
|
||||
var newLeft = currentLeft + (deltaX * i.railXRatio);
|
||||
var maxLeft = i.scrollbarXRail.getBoundingClientRect().left + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
|
||||
|
||||
if (newLeft < 0) {
|
||||
i.scrollbarXLeft = 0;
|
||||
@@ -24,8 +25,8 @@ function bindMouseScrollXHandler(element, i) {
|
||||
i.scrollbarXLeft = newLeft;
|
||||
}
|
||||
|
||||
var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - i.scrollbarXWidth));
|
||||
element.scrollLeft = scrollLeft;
|
||||
var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
|
||||
updateScroll(element, 'left', scrollLeft);
|
||||
}
|
||||
|
||||
var mouseMoveHandler = function (e) {
|
||||
@@ -42,7 +43,7 @@ function bindMouseScrollXHandler(element, i) {
|
||||
|
||||
i.event.bind(i.scrollbarX, 'mousedown', function (e) {
|
||||
currentPageX = e.pageX;
|
||||
currentLeft = h.toInt(d.css(i.scrollbarX, 'left'));
|
||||
currentLeft = h.toInt(d.css(i.scrollbarX, 'left')) * i.railXRatio;
|
||||
h.startScrolling(element, 'x');
|
||||
|
||||
i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
|
||||
@@ -58,8 +59,8 @@ function bindMouseScrollYHandler(element, i) {
|
||||
var currentPageY = null;
|
||||
|
||||
function updateScrollTop(deltaY) {
|
||||
var newTop = currentTop + deltaY;
|
||||
var maxTop = i.containerHeight - i.scrollbarYHeight;
|
||||
var newTop = currentTop + (deltaY * i.railYRatio);
|
||||
var maxTop = i.scrollbarYRail.getBoundingClientRect().top + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
|
||||
|
||||
if (newTop < 0) {
|
||||
i.scrollbarYTop = 0;
|
||||
@@ -69,8 +70,8 @@ function bindMouseScrollYHandler(element, i) {
|
||||
i.scrollbarYTop = newTop;
|
||||
}
|
||||
|
||||
var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - i.scrollbarYHeight));
|
||||
element.scrollTop = scrollTop;
|
||||
var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
|
||||
updateScroll(element, 'top', scrollTop);
|
||||
}
|
||||
|
||||
var mouseMoveHandler = function (e) {
|
||||
@@ -87,7 +88,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);
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
var h = require('../../lib/helper')
|
||||
, instances = require('../instances')
|
||||
, updateGeometry = require('../update-geometry');
|
||||
, updateGeometry = require('../update-geometry')
|
||||
, updateScroll = require('../update-scroll');
|
||||
|
||||
function bindKeyboardHandler(element, i) {
|
||||
var hovered = false;
|
||||
@@ -80,6 +81,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 +108,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);
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
var h = require('../../lib/helper')
|
||||
, instances = require('../instances')
|
||||
, updateGeometry = require('../update-geometry');
|
||||
, updateGeometry = require('../update-geometry')
|
||||
, updateScroll = require('../update-scroll');
|
||||
|
||||
function bindMouseWheelHandler(element, i) {
|
||||
var shouldPrevent = false;
|
||||
@@ -100,24 +101,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;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
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 +29,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
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
'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 +34,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);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,10 @@ module.exports = function (element, userSettings) {
|
||||
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);
|
||||
|
||||
@@ -21,6 +21,15 @@ function Instance(element) {
|
||||
i.contentHeight = null;
|
||||
|
||||
i.isRtl = d.css(element, 'direction') === "rtl";
|
||||
i.isNegativeScroll = (function () {
|
||||
var originalScrollLeft = element.scrollLeft;
|
||||
var result = null;
|
||||
element.scrollLeft = -1;
|
||||
result = element.scrollLeft < 0;
|
||||
element.scrollLeft = originalScrollLeft;
|
||||
return result;
|
||||
})();
|
||||
i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
|
||||
i.event = new EventManager();
|
||||
i.ownerDocument = element.ownerDocument || document;
|
||||
|
||||
@@ -33,8 +42,12 @@ function Instance(element) {
|
||||
i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
|
||||
i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : h.toInt(d.css(i.scrollbarXRail, 'top'));
|
||||
i.railBorderXWidth = h.toInt(d.css(i.scrollbarXRail, 'borderLeftWidth')) + h.toInt(d.css(i.scrollbarXRail, 'borderRightWidth'));
|
||||
// Set rail to display:block to calculate margins
|
||||
d.css(i.scrollbarXRail, 'display', 'block');
|
||||
i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
|
||||
d.css(i.scrollbarXRail, 'display', '');
|
||||
i.railXWidth = null;
|
||||
i.railXRatio = null;
|
||||
|
||||
i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element);
|
||||
i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
|
||||
@@ -46,8 +59,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) {
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
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) {
|
||||
@@ -21,7 +22,7 @@ function getThumbSize(i, thumbSize) {
|
||||
function updateCss(element, i) {
|
||||
var xRailOffset = {width: i.railXWidth};
|
||||
if (i.isRtl) {
|
||||
xRailOffset.left = element.scrollLeft + i.containerWidth - i.contentWidth;
|
||||
xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth;
|
||||
} else {
|
||||
xRailOffset.left = element.scrollLeft;
|
||||
}
|
||||
@@ -35,13 +36,13 @@ function updateCss(element, i) {
|
||||
var yRailOffset = {top: element.scrollTop, height: i.railYHeight};
|
||||
if (i.isScrollbarYUsingRight) {
|
||||
if (i.isRtl) {
|
||||
yRailOffset.right = i.contentWidth - element.scrollLeft - i.scrollbarYRight - i.scrollbarYOuterWidth;
|
||||
yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth;
|
||||
} else {
|
||||
yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
|
||||
}
|
||||
} else {
|
||||
if (i.isRtl) {
|
||||
yRailOffset.left = element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth;
|
||||
yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth;
|
||||
} else {
|
||||
yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
|
||||
}
|
||||
@@ -60,18 +61,32 @@ 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);
|
||||
}
|
||||
|
||||
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));
|
||||
i.scrollbarXLeft = h.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
|
||||
} else {
|
||||
i.scrollbarXActive = false;
|
||||
i.scrollbarXWidth = 0;
|
||||
@@ -82,13 +97,14 @@ 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 {
|
||||
i.scrollbarYActive = false;
|
||||
i.scrollbarYHeight = 0;
|
||||
i.scrollbarYTop = 0;
|
||||
element.scrollTop = 0;
|
||||
updateScroll(element, 'top', 0);
|
||||
}
|
||||
|
||||
if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
|
||||
|
||||
105
src/js/plugin/update-scroll.js
Normal file
105
src/js/plugin/update-scroll.js
Normal file
@@ -0,0 +1,105 @@
|
||||
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
|
||||
* Licensed under the MIT License
|
||||
*/
|
||||
'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 = 0;
|
||||
element.dispatchEvent(yStartEvent);
|
||||
return; // don't allow negative scroll
|
||||
}
|
||||
|
||||
if (axis === 'left' && value <= 0) {
|
||||
element.scrollLeft = 0;
|
||||
element.dispatchEvent(xStartEvent);
|
||||
return; // don't allow negative scroll
|
||||
}
|
||||
|
||||
var i = instances.get(element);
|
||||
|
||||
if (axis === 'top' && value > i.contentHeight - i.containerHeight) {
|
||||
element.scrollTop = i.contentHeight - i.containerHeight;
|
||||
element.dispatchEvent(yEndEvent);
|
||||
return; // don't allow scroll past container
|
||||
}
|
||||
|
||||
if (axis === 'left' && value > i.contentWidth - i.containerWidth) {
|
||||
element.scrollLeft = i.contentWidth - i.containerWidth;
|
||||
element.dispatchEvent(xEndEvent);
|
||||
return; // don't allow scroll past container
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -4,18 +4,32 @@
|
||||
'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);
|
||||
|
||||
if (!i) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Recalcuate negative scrollLeft adjustment
|
||||
i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
|
||||
|
||||
// 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', '');
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user