Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
55
README.md
55
README.md
@@ -308,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>
|
||||
@@ -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;
|
||||
|
||||
113
gulpfile.js
113
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';
|
||||
} else {
|
||||
path.basename = 'perfect-scrollbar.' + path.basename;
|
||||
}
|
||||
}))
|
||||
.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({
|
||||
@@ -125,7 +112,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']);
|
||||
|
||||
30
package.json
30
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "perfect-scrollbar",
|
||||
"version": "0.6.3",
|
||||
"version": "0.6.6",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,7 +14,9 @@ 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 = i.railYRatio * (e.pageY - window.scrollY - pageOffset(i.scrollbarYRail).top - halfOfScrollbarLength);
|
||||
@@ -26,13 +29,15 @@ 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 = i.railXRatio * (e.pageX - window.scrollX - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength);
|
||||
@@ -45,7 +50,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();
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
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;
|
||||
@@ -25,7 +26,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) {
|
||||
@@ -70,7 +71,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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
@@ -60,10 +61,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);
|
||||
}
|
||||
|
||||
@@ -90,7 +104,7 @@ module.exports = function (element) {
|
||||
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);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -11,6 +11,10 @@ var d = require('../lib/dom')
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user