Compare commits

...

46 Commits
0.6.2 ... 0.6.7

Author SHA1 Message Date
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
Hyunje Alex Jun
b1d7aa0e64 Release 0.6.4
1. Add null-check for instances.
2. Add 'stopPropgationOnClick' option.
2015-07-25 02:28:12 +09:00
Hyunje Alex Jun
49e39f513d Update README.md 2015-07-25 02:26:55 +09:00
Jun
89f4226778 Merge pull request #366 from dorilla/feature/stop-propagation-on-click
Allow the clicking of a rail to propagate
2015-07-25 02:23:42 +09:00
Dan Maglasang
79f4cfcf5f Update README.md 2015-07-22 22:47:33 -04:00
Dan Maglasang
158b113d18 Allow the clicking of a rail to propagate 2015-07-22 22:43:38 -04:00
Hyunje Alex Jun
6c642d8a47 Just early return instead of throwing an error for no instance. 2015-07-14 12:22:40 +09:00
Hyunje Alex Jun
f9f20eeb6f Add null-check when updating or destroying an instance.
Throw an error when an instance is not found.
2015-07-07 15:25:16 +09:00
Hyunje Alex Jun
1f082a2e04 Release 0.6.3
1. Improve toInt
2. Stop propagating click event through scrollbar rails.
3. IE touch device fix.
4. RTL support.
5. Other minor fixes.
2015-06-22 22:21:25 +09:00
Hyunje Alex Jun
b19c5e0765 Chmod 644 README.md 2015-06-22 21:38:43 +09:00
ahspw
3dbf20a5d0 perfect RTL support 2015-06-22 21:36:43 +09:00
guandai
db855ceca1 update readme 2015-06-22 21:28:47 +09:00
Jun
84b74926e3 Merge pull request #347 from danthewolfe/ie-touch-device
IE touch device fix
2015-06-17 13:02:22 +09:00
dan
d6bd30f2da IE touch device fix
Add vendor specific css for IE to handle let javascript handle touch events instead of letting css attempt to handle them. Without this CSS property IE touch devices do not work.
2015-06-16 15:43:00 -04:00
Hyunje Alex Jun
fc28ceb4ea Stop propagating click event through scrollbar rails.
Fixes #326.
2015-04-29 13:08:03 +09:00
Hyunje Alex Jun
ca4d835129 Simplify parseInt.
Because `~~` isn't necessarily faster than `parseInt` in every browser.
Now I think it'd be better to make it readable and simple.
2015-04-15 21:41:11 +09:00
Jun
88b4e2fc19 Merge pull request #321 from juxtapos/toInt-fix
changed toInt()'s function behavior
2015-04-15 21:39:10 +09:00
Claus Augusti
de32082a62 changed the toInt()'s function behavior so that it returns 0 on empty strings 2015-04-15 13:56:38 +02:00
DanielApt
7ba25d020c Add an editor config file 2015-04-14 13:57:45 +09:00
Jun
08d559561e Merge pull request #320 from jaronkk/scrollbar-margins
Support large and percentage margins on scrollbar rails
2015-04-14 13:56:47 +09:00
Jaron Kennel
046ce954fd Fix gulp watch to call sass instead of css 2015-04-13 13:12:09 -04:00
Jaron Kennel
a40ab40695 Fix clicking and dragging the scrollbar rails with large margin values.
Fix initial rail height/width calculation: Set the rails to display:block temporarily to correctly calculate percentage margins
Account for scrolltop/left on the document.
2015-04-13 13:12:00 -04:00
28 changed files with 593 additions and 220 deletions

14
.editorconfig Normal file
View 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

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

2
.gitignore vendored
View File

@@ -1,4 +1,4 @@
.DS_Store
node_modules
/dist
.idea
.idea

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

116
README.md
View File

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

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

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,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({

View File

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

View File

@@ -62,6 +62,7 @@ $ps-bar-hover: #999;
}
.ps-container {
-ms-touch-action: none;
overflow: hidden !important;
&.ps-active-x > .ps-scrollbar-x-rail,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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