Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2b66c76ad | ||
|
|
85009c34cd | ||
|
|
7e39eb3d68 | ||
|
|
085cd7abdd | ||
|
|
6edd7a183c | ||
|
|
735c6c0bf3 | ||
|
|
553756b346 | ||
|
|
4707acc287 | ||
|
|
5f0a423128 | ||
|
|
6d2c6ac8ec | ||
|
|
d1340f1b85 | ||
|
|
4a988b5a21 | ||
|
|
1a39d76e48 | ||
|
|
9fc34100df | ||
|
|
d74bdcccec | ||
|
|
5f34edc8c7 | ||
|
|
ce3a199cb3 | ||
|
|
9c485584b9 | ||
|
|
d5db8ca18e | ||
|
|
89174ed99f | ||
|
|
6e7e3f94fa | ||
|
|
7d61475e1d | ||
|
|
2f8daae695 | ||
|
|
5ce0d77f87 | ||
|
|
f811bbcab5 | ||
|
|
4593eb9115 | ||
|
|
b3b1bc2454 | ||
|
|
25e5be13ff | ||
|
|
f683b01959 | ||
|
|
6d2f203441 | ||
|
|
a4808f662e | ||
|
|
98fa15167a | ||
|
|
06929ae685 | ||
|
|
aa63ff0370 | ||
|
|
c7ddde69c2 | ||
|
|
69e3fb2688 | ||
|
|
fad7f8b4a6 | ||
|
|
0deb4c9bc7 | ||
|
|
11fcd09a99 | ||
|
|
0fc5c69b3f | ||
|
|
898928b686 | ||
|
|
ce7146121f | ||
|
|
908cee5490 | ||
|
|
b3880ca638 | ||
|
|
7123891d4d | ||
|
|
4c00a7fdb9 | ||
|
|
3719dd614c | ||
|
|
68dbc427ea | ||
|
|
34135d6ef0 | ||
|
|
0ab95f2d57 | ||
|
|
985980a892 | ||
|
|
fdc8d64fd9 | ||
|
|
26852236cc | ||
|
|
e0510b5fad | ||
|
|
838ccbba77 | ||
|
|
4198b23231 | ||
|
|
3eb2a49109 | ||
|
|
1b2c853972 | ||
|
|
e9d7cc97c8 | ||
|
|
9016f207e9 | ||
|
|
aec4e37f61 | ||
|
|
269a1dc402 | ||
|
|
2cac43ef39 | ||
|
|
b0a38741df | ||
|
|
edaeccebf2 | ||
|
|
42364c4d43 | ||
|
|
f20a8532ff | ||
|
|
7621a2488c | ||
|
|
205c6d0223 | ||
|
|
ad5cd4fe53 | ||
|
|
dc951a3804 | ||
|
|
9996b1c8e3 | ||
|
|
f14b6a0d47 | ||
|
|
9580e08886 | ||
|
|
a2b2a77de1 | ||
|
|
e63d4c03cb | ||
|
|
d277a363b0 | ||
|
|
4a661f181f | ||
|
|
bd7134f33d | ||
|
|
6f63623b93 | ||
|
|
cfc658d648 | ||
|
|
181265261b | ||
|
|
db65fe0f6a | ||
|
|
7e0d5f5dc5 | ||
|
|
e0d6243f24 | ||
|
|
3d91c6f098 | ||
|
|
636eaffd41 | ||
|
|
3ba211133d | ||
|
|
40b1510d49 | ||
|
|
b959edbf78 | ||
|
|
c49cf7905e | ||
|
|
4c08b0e089 |
8
.github/ISSUE_TEMPLATE.md
vendored
Normal file
8
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
Make sure these boxes are checked before submitting your issue -- thank you!
|
||||
|
||||
- [ ] Check [FAQ](https://github.com/noraesae/perfect-scrollbar/wiki/FAQ)
|
||||
- [ ] Search if there's already one reported in Issues
|
||||
- [ ] Prepare a JSFiddle reproducing the issue
|
||||
- Perfect Scrollbar JSFiddle: https://jsfiddle.net/DanielApt/xv0rrxv3/
|
||||
- With jQuery: https://jsfiddle.net/DanielApt/gbfLazpx/
|
||||
- [ ] Provide a page or source code where the issue can be checked
|
||||
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
Thank you very much for your contribution! Please make sure the followings
|
||||
are checked.
|
||||
|
||||
- [ ] Read [CONTRIBUTING.md](../CONTRIBUTING.md)
|
||||
- [ ] Run `gulp` to make sure it builds and lints successfully
|
||||
- [ ] Provide the scenario this PR will address(some JSFiddles will be perfect)
|
||||
- Perfect Scrollbar JSFiddle: https://jsfiddle.net/DanielApt/xv0rrxv3/
|
||||
- With jQuery: https://jsfiddle.net/DanielApt/gbfLazpx/
|
||||
- [ ] Refer to concerning issues if exist
|
||||
@@ -1,9 +0,0 @@
|
||||
.DS_Store
|
||||
|
||||
/.eslintrc
|
||||
/.gitignore
|
||||
/.travis.yml
|
||||
/gulpfile.js
|
||||
/examples
|
||||
|
||||
node_modules
|
||||
@@ -1,6 +1,5 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.12
|
||||
- 4
|
||||
deploy:
|
||||
provider: releases
|
||||
|
||||
74
CONTRIBUTING.md
Normal file
74
CONTRIBUTING.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Contributing
|
||||
|
||||
I *really* welcome contributions! Please feel free to fork and issue pull requests when...
|
||||
|
||||
* You have a very nice idea to improve this plugin!
|
||||
* You found a bug!
|
||||
* You're good at English and can help my bad English!
|
||||
|
||||
For IE problems, please refer to [IE Support](https://github.com/noraesae/perfect-scrollbar#ie-support).
|
||||
|
||||
## Introduction
|
||||
First of all, thank you in advance for your contribution!
|
||||
|
||||
This document will introduce something you should know before making some contributions to **perfect-scrollbar**. I'll try to explain as easy as possible. If there are something missed or not well-documented, please let me know.
|
||||
|
||||
Email: me@noraesae.net
|
||||
|
||||
## Directory Structure
|
||||
Please don't edit files in the `out` subdirectory as they are generated via Gulp. You'll find source code in the `src` subdirectory!
|
||||
|
||||
`examples` directory is for the example sources. If you have any example you want to add with a new feature, please add it in the directory.
|
||||
|
||||
## Code Conventions
|
||||
Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.**
|
||||
|
||||
Basically, I try to follow [Douglas Crockford's JavaScript Code Conventions](http://javascript.crockford.com/code.html).
|
||||
|
||||
You can check if your code fits in the convention with `gulp lint`.
|
||||
|
||||
## Getting Started
|
||||
First, ensure that you have stable [Node.js](https://nodejs.org/) and [npm](https://npmjs.com) installed.
|
||||
|
||||
Test if Gulp CLI is installed by running `gulp --version`. If the command isn't found, run `npm install -g gulp`. For more information about installing Gulp, see the Gulp's [Getting Started](https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md).
|
||||
|
||||
If `gulp` is installed, follow the steps below.
|
||||
|
||||
1. Fork and clone the repo.
|
||||
1. Run `npm install` to install all dev dependencies.
|
||||
1. Run `gulp` to check if Gulp works well.
|
||||
|
||||
Assuming that you don't see any error, you're ready to go.
|
||||
|
||||
## Linting Sources
|
||||
|
||||
You can use `gulp lint` command to lint the source files. If there're warnings with the command, it means that there are something that don't fit into the convention. Please modify the source to fit.
|
||||
|
||||
## Building Sources
|
||||
|
||||
You can use the `gulp build` command to build source files into output files.
|
||||
|
||||
If you want to watch the modification and build automatically during development, use the `gulp serve` command. It'll automatically rebuild the code when there's any change in it. It will also reload example pages, which is quite helpful.
|
||||
|
||||
## Submitting pull requests
|
||||
|
||||
1. Create a new branch. Working in your `master` branch is okay, but not recommended.
|
||||
1. Modify the sources.
|
||||
1. Run `gulp` to see if the code fit into the code convention and build without an error. Repeat steps 2-3 until done.
|
||||
1. Update the documentation to reflect any changes.
|
||||
1. Create examples if needed.
|
||||
1. Push to your fork and submit a pull request.
|
||||
|
||||
For further information about pull requests, please refer to GitHub's [Using Pull Requests](https://help.github.com/articles/using-pull-requests).
|
||||
|
||||
## Code Review
|
||||
|
||||
When the pull request is created, anyone can review the source code. After the review is finished and the patch doesn't have any problem, it'll be merged.
|
||||
|
||||
## Conclusion
|
||||
|
||||
The process looks somewhat difficult, but it's necessary to avoid maintanance issues and make the code easy to read and use.
|
||||
|
||||
If there is any opinion or question, please feel free to contact me.
|
||||
|
||||
Email: me@noraesae.net
|
||||
141
README.md
141
README.md
@@ -52,16 +52,26 @@ It's cool, isn't it?
|
||||
|
||||
## Install
|
||||
|
||||
#### NPM
|
||||
|
||||
The best way to install and use perfect-scrollbar is with NPM.
|
||||
It's registered on [npm](https://www.npmjs.org/package/perfect-scrollbar) as `perfect-scrollbar`.
|
||||
It's registered on [npm](https://www.npmjs.com/package/perfect-scrollbar) as `perfect-scrollbar`.
|
||||
|
||||
```
|
||||
$ npm install perfect-scrollbar
|
||||
```
|
||||
|
||||
#### Rails
|
||||
|
||||
In the case you would like to have perfect-scrollbar in your Rails application, there is the [perfect-scrollbar-rails gem](https://github.com/YourCursus/perfect-scrollbar-rails).
|
||||
|
||||
#### Manually
|
||||
|
||||
You can download the latest stable version with download links [here](http://noraesae.github.io/perfect-scrollbar/).
|
||||
You also can find all releases on [Releases](https://github.com/noraesae/perfect-scrollbar/releases).
|
||||
|
||||
#### From sources
|
||||
|
||||
If you want to use the development version of the plugin, use the
|
||||
source files which are not minified. They're in the `src` directory.
|
||||
The development version may be unstable, but some known bugs may
|
||||
@@ -74,6 +84,7 @@ $ npm install
|
||||
$ gulp # will lint and build the source code.
|
||||
```
|
||||
|
||||
#### Bower
|
||||
|
||||
There is a Bower package for perfect-scrollbar as well. It is managed
|
||||
under the [perfect-scrollbar-bower](https://github.com/noraesae/perfect-scrollbar-bower)
|
||||
@@ -83,27 +94,39 @@ repository. The plugin is registered as `perfect-scrollbar`.
|
||||
$ bower install perfect-scrollbar
|
||||
```
|
||||
|
||||
#### CDNs
|
||||
|
||||
You can also load it from [cdnjs](http://cdnjs.com/).
|
||||
It is registered as [`jquery.perfect-scrollbar`](http://www.cdnjs.com/libraries/jquery.perfect-scrollbar).
|
||||
* [cdnjs](http://www.cdnjs.com/libraries/jquery.perfect-scrollbar)
|
||||
* [JSDelivr](https://www.jsdelivr.com/projects/perfect-scrollbar)
|
||||
|
||||
## Requirements
|
||||
#### JSFiddle
|
||||
|
||||
To make this plugin *perfect*, some requirements were unavoidable.
|
||||
But, they're all very trivial and there is nothing to worry about.
|
||||
You can fork the following JSFiddles for testing and experimenting purposes:
|
||||
|
||||
* [Perfect Scrollbar](https://jsfiddle.net/DanielApt/xv0rrxv3/)
|
||||
* [Perfect Scrollbar (jQuery)](https://jsfiddle.net/DanielApt/gbfLazpx/)
|
||||
|
||||
## Before using perfect-scrollbar
|
||||
|
||||
The following requirements should meet.
|
||||
|
||||
* the container must have a 'position' css style.
|
||||
* the container must be a normal container element.
|
||||
* PS may not work well in `body`, `textarea`, `iframe` or flexbox.
|
||||
|
||||
The following requirements are included in the basic CSS, but please
|
||||
keep in mind when you'd like to change the CSS files.
|
||||
|
||||
* the container must have an 'overflow:hidden' css style.
|
||||
* the container must have an 'overflow: hidden' css style.
|
||||
* the scrollbar's position must be 'absolute'.
|
||||
* the scrollbar-x must have a 'bottom' css style, and the scrollbar-y
|
||||
must have a 'right' css style.
|
||||
|
||||
Please keep in mind that perfect-scrollbar won't completely emulate native
|
||||
scrolls. Scroll hooking is generally considered as bad practice, and
|
||||
perfect-scrollbar should be used with care. Unless custom scroll is really needed,
|
||||
please consider using native scrolls.
|
||||
|
||||
## How to use
|
||||
|
||||
First of all, please check if the container element meets the
|
||||
@@ -155,7 +178,7 @@ If the size of your container or content changes, call `update`.
|
||||
Ps.update(container);
|
||||
```
|
||||
|
||||
If you want to destory the scrollbar, use `destroy`.
|
||||
If you want to destroy the scrollbar, use `destroy`.
|
||||
|
||||
```javascript
|
||||
Ps.destroy(container);
|
||||
@@ -238,12 +261,12 @@ define([
|
||||
'perfectScrollbarJquery'
|
||||
],
|
||||
function (angular) {
|
||||
var myApp = angular.module('myApp', [])
|
||||
.run(function() {
|
||||
var app = angular.module('myApp', []);
|
||||
app.run(function () {
|
||||
window.Ps = require('perfectScrollbar');
|
||||
require('perfectScrollbarJQuery');
|
||||
})
|
||||
return myApp;
|
||||
});
|
||||
return app;
|
||||
});
|
||||
```
|
||||
|
||||
@@ -256,7 +279,7 @@ Ps.initialize(container);
|
||||
Ps.update(container);
|
||||
|
||||
// or by jQuery:
|
||||
var imgLoader = $("#imgLoader")
|
||||
var imgLoader = $('#imgLoader')
|
||||
imgLoader.perfectScrollbar();
|
||||
```
|
||||
|
||||
@@ -264,61 +287,58 @@ imgLoader.perfectScrollbar();
|
||||
|
||||
perfect-scrollbar supports optional parameters.
|
||||
|
||||
### handlers
|
||||
It is a list of handlers to use to scroll the element.
|
||||
**Default**: `['click-rail', 'drag-scrollbar', 'keyboard', 'wheel', 'touch']`
|
||||
**Disabled by default**: `'selection'`
|
||||
|
||||
### wheelSpeed
|
||||
The scroll speed applied to mousewheel event.
|
||||
**Default: 1**
|
||||
The scroll speed applied to mousewheel event.
|
||||
**Default**: `1`
|
||||
|
||||
### wheelPropagation
|
||||
If this option is true, when the scroll reaches the end of the side, mousewheel event will be propagated to parent element.
|
||||
**Default: false**
|
||||
If this option is true, when the scroll reaches the end of the side, mousewheel event will be propagated to parent element.
|
||||
**Default**: `false`
|
||||
|
||||
### swipePropagation
|
||||
If this option is true, when the scroll reaches the end of the side, touch scrolling will be propagated to parent element.
|
||||
**Default: true**
|
||||
If this option is true, when the scroll reaches the end of the side, touch scrolling will be propagated to parent element.
|
||||
**Default**: `true`
|
||||
|
||||
### minScrollbarLength
|
||||
When set to an integer value, the thumb part of the scrollbar will not shrink below that number of pixels.
|
||||
**Default: null**
|
||||
When set to an integer value, the thumb part of the scrollbar will not shrink below that number of pixels.
|
||||
**Default**: `null`
|
||||
|
||||
### maxScrollbarLength
|
||||
When set to an integer value, the thumb part of the scrollbar will not expand over that number of pixels.
|
||||
**Default: null**
|
||||
When set to an integer value, the thumb part of the scrollbar will not expand over that number of pixels.
|
||||
**Default**: `null`
|
||||
|
||||
### useBothWheelAxes
|
||||
When set to true, and only one (vertical or horizontal) scrollbar is visible then both vertical and horizontal scrolling will affect the scrollbar.
|
||||
**Default: false**
|
||||
|
||||
### useKeyboard
|
||||
When set to true, the scroll works with arrow keys on the keyboard. The element is scrolled only when the mouse cursor hovers the element.
|
||||
**Default: true**
|
||||
When set to true, and only one (vertical or horizontal) scrollbar is visible then both vertical and horizontal scrolling will affect the scrollbar.
|
||||
**Default**: `false`
|
||||
|
||||
### suppressScrollX
|
||||
When set to true, the scroll bar in X axis will not be available, regardless of the content width.
|
||||
**Default: false**
|
||||
When set to true, the scroll bar in X axis will not be available, regardless of the content width.
|
||||
**Default**: `false`
|
||||
|
||||
### suppressScrollY
|
||||
When set to true, the scroll bar in Y axis will not be available, regardless of the content height.
|
||||
**Default: false**
|
||||
When set to true, the scroll bar in Y axis will not be available, regardless of the content height.
|
||||
**Default**: `false`
|
||||
|
||||
### scrollXMarginOffset
|
||||
The number of pixels the content width can surpass the container width without enabling the X axis scroll bar. Allows some "wiggle room" or "offset break", so that X axis scroll bar is not enabled just because of a few pixels.
|
||||
**Default: 0**
|
||||
The number of pixels the content width can surpass the container width without enabling the X axis scroll bar. Allows some "wiggle room" or "offset break", so that X axis scroll bar is not enabled just because of a few pixels.
|
||||
**Default**: `0`
|
||||
|
||||
### scrollYMarginOffset
|
||||
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**
|
||||
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**
|
||||
### autoupdate
|
||||
When set to true, the scroll will be updated when an element is added or removed from the content.
|
||||
**Default**: `true`
|
||||
|
||||
### theme
|
||||
A string. It's a class name added to the container element. The class name is prepended with `ps-theme-`. So default theme class name is `ps-theme-default`. In order to create custom themes with scss use `ps-container($theme)` mixin, where `$theme` is a scss map.
|
||||
**Default: 'default'**
|
||||
A string. It's a class name added to the container element. The class name is prepended with `ps-theme-`. So default theme class name is `ps-theme-default`. In order to create custom themes with scss use `ps-container($theme)` mixin, where `$theme` is a scss map.
|
||||
**Default**: `'default'`
|
||||
|
||||
**Example 1:**
|
||||
|
||||
@@ -329,15 +349,15 @@ Ps.initialize(container, {
|
||||
});
|
||||
```
|
||||
Create a class name prefixed with `.ps-theme-`. Include `ps-container()` mixin. It's recommended to use `map-merge()` to extend `$ps-theme-default` map with your custom styles.
|
||||
```css#
|
||||
```scss
|
||||
.ps-theme-my-theme-name {
|
||||
@include ps-container(map-merge($ps-theme-default, (
|
||||
border-radius: 0,
|
||||
scrollbar-x-rail-height: 20px,
|
||||
scrollbar-x-height: 20px,
|
||||
scrollbar-y-rail-width: 20px,
|
||||
scrollbar-y-width: 20px,)
|
||||
));
|
||||
scrollbar-y-width: 20px
|
||||
)));
|
||||
}
|
||||
```
|
||||
|
||||
@@ -380,6 +400,9 @@ 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.
|
||||
|
||||
### ps-dom-change
|
||||
This event fires when dom elements have been added to or removed from the content.
|
||||
|
||||
You can listen to these events either with vanilla JavaScript
|
||||
```javascript
|
||||
document.addEventListener('ps-scroll-x', function () {
|
||||
@@ -393,24 +416,20 @@ $(document).on('ps-scroll-x', function () {
|
||||
})
|
||||
```
|
||||
|
||||
## Contribution
|
||||
## Tips
|
||||
|
||||
#### Please read [Contributing](https://github.com/noraesae/perfect-scrollbar/wiki/Contributing) in the wiki before making any contribution.
|
||||
### Scrolling children inside perfect-scrollbar
|
||||
|
||||
|
||||
I *really* welcome contributions! Please feel free to fork and issue pull requests when...
|
||||
|
||||
* You have a very nice idea to improve this plugin!
|
||||
* You found a bug!
|
||||
* You're good at English and can help my bad English!
|
||||
|
||||
For IE problems, please refer to [IE Support](https://github.com/noraesae/perfect-scrollbar#ie-support).
|
||||
You can natively scroll children inside `perfect-scrollbar` with the mouse-wheel. Scrolling automatically works if
|
||||
the child is a `textarea`. All other elements need to have the `ps-child` class. This is demonstrated in [`/examples/children-native-scroll.html`](examples/children-native-scroll.html)
|
||||
|
||||
## IE Support
|
||||
|
||||
The plugin would work in IEs >= IE9 (not well, though).
|
||||
The plugin is designed to work in modern browsers, including the very latest
|
||||
version of IE and Edge. Specifically, it should work in IEs >= IE10. If there
|
||||
is any issue in the browsers, please [file it](https://github.com/noraesae/perfect-scrollbar/issues).
|
||||
|
||||
**The patches to fix problems in IE<=8 won't be accepted.**
|
||||
**The patches to fix problems in IE<=9 won't be accepted.**
|
||||
|
||||
When old IEs should be supported, please fork the project and
|
||||
make patches personally.
|
||||
|
||||
73
examples/children-native-scroll.html
Normal file
73
examples/children-native-scroll.html
Normal file
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>perfect-scrollbar example</title>
|
||||
<link href="../dist/css/perfect-scrollbar.css" rel="stylesheet">
|
||||
<script src="../dist/js/perfect-scrollbar.js"></script>
|
||||
<style>
|
||||
.contentHolder { position:relative; margin:0px auto; padding:0px; width: 600px; height: 400px; overflow: auto; }
|
||||
.contentHolder .content { background-image: url('./azusa.jpg'); width: 1280px; height: 720px; }
|
||||
.my-list, textarea {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 130px;
|
||||
height: 200px;
|
||||
overflow: scroll;
|
||||
background-color: rgba(255,255,255,0.6);
|
||||
}
|
||||
|
||||
.my-list {
|
||||
left: 140px;
|
||||
}
|
||||
|
||||
.my-list-two {
|
||||
left: 280px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
box-sizing: border-box;
|
||||
padding: 10px 5px;
|
||||
border-width: 0 0 1px 0;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li:nth-child(even) {
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
textarea {
|
||||
font-size: 120%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<div id="Default" class="contentHolder">
|
||||
<div class="content">
|
||||
<textarea cols="20" rows="50">
|
||||
Children inside perfect scrollbar can be natively scrolled by the mousewheel. It automatically works for textarea elements, other elements need the .ps-child class.
|
||||
</textarea>
|
||||
<div class="ps-child my-list">
|
||||
<code>overflow: scroll</code>
|
||||
<ul><li>One</li><li>Two</li><li>Three</li><li>Four</li><li>Five</li><li>Six</li><li>Seven</li><li>Eight</li></ul>
|
||||
</div>
|
||||
<div class="ps-child my-list my-list-two">
|
||||
<code>overflow: auto</code>
|
||||
<ul><li>One</li><li>Two</li><li>Three</li><li>Four</li><li>Five</li><li>Six</li><li>Seven</li><li>Eight</li></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
window.onload = function () {
|
||||
Ps.initialize(document.querySelector('#Default'));
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
190
examples/custom-theme.css
Normal file
190
examples/custom-theme.css
Normal file
@@ -0,0 +1,190 @@
|
||||
.ps-container {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
overflow: hidden !important;
|
||||
-ms-overflow-style: none; }
|
||||
@supports (-ms-overflow-style: none) {
|
||||
.ps-container {
|
||||
overflow: auto !important; } }
|
||||
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
|
||||
.ps-container {
|
||||
overflow: auto !important; } }
|
||||
.ps-container.ps-active-x > .ps-scrollbar-x-rail,
|
||||
.ps-container.ps-active-y > .ps-scrollbar-y-rail {
|
||||
display: block;
|
||||
background-color: transparent; }
|
||||
.ps-container.ps-in-scrolling {
|
||||
pointer-events: none; }
|
||||
.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
|
||||
background-color: #999; }
|
||||
.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
|
||||
background-color: #999; }
|
||||
.ps-container > .ps-scrollbar-x-rail {
|
||||
display: none;
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
opacity: 0;
|
||||
transition: background-color .2s linear, opacity .2s linear;
|
||||
bottom: 0px;
|
||||
/* there must be 'bottom' for ps-scrollbar-x-rail */
|
||||
height: 15px; }
|
||||
.ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x {
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
background-color: #aaa;
|
||||
border-radius: 6px;
|
||||
transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;
|
||||
bottom: 2px;
|
||||
/* there must be 'bottom' for ps-scrollbar-x */
|
||||
height: 6px; }
|
||||
.ps-container > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x, .ps-container > .ps-scrollbar-x-rail:active > .ps-scrollbar-x {
|
||||
height: 11px; }
|
||||
.ps-container > .ps-scrollbar-y-rail {
|
||||
display: none;
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
opacity: 0;
|
||||
transition: background-color .2s linear, opacity .2s linear;
|
||||
right: 0;
|
||||
/* there must be 'right' for ps-scrollbar-y-rail */
|
||||
width: 15px; }
|
||||
.ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y {
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
background-color: #aaa;
|
||||
border-radius: 6px;
|
||||
transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;
|
||||
right: 2px;
|
||||
/* there must be 'right' for ps-scrollbar-y */
|
||||
width: 6px; }
|
||||
.ps-container > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y, .ps-container > .ps-scrollbar-y-rail:active > .ps-scrollbar-y {
|
||||
width: 11px; }
|
||||
.ps-container:hover.ps-in-scrolling {
|
||||
pointer-events: none; }
|
||||
.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
|
||||
background-color: #999; }
|
||||
.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
|
||||
background-color: #999; }
|
||||
.ps-container:hover > .ps-scrollbar-x-rail,
|
||||
.ps-container:hover > .ps-scrollbar-y-rail {
|
||||
opacity: 0.6; }
|
||||
.ps-container:hover > .ps-scrollbar-x-rail:hover {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-container:hover > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x {
|
||||
background-color: #999; }
|
||||
.ps-container:hover > .ps-scrollbar-y-rail:hover {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-container:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y {
|
||||
background-color: #999; }
|
||||
|
||||
/*
|
||||
this file is built into custom-theme.css
|
||||
|
||||
$ node-sass examples/custom-theme.scss -o examples/
|
||||
*/
|
||||
.ps-theme-square {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
overflow: hidden !important;
|
||||
-ms-overflow-style: none; }
|
||||
@supports (-ms-overflow-style: none) {
|
||||
.ps-theme-square {
|
||||
overflow: auto !important; } }
|
||||
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
|
||||
.ps-theme-square {
|
||||
overflow: auto !important; } }
|
||||
.ps-theme-square.ps-active-x > .ps-scrollbar-x-rail,
|
||||
.ps-theme-square.ps-active-y > .ps-scrollbar-y-rail {
|
||||
display: block;
|
||||
background-color: transparent; }
|
||||
.ps-theme-square.ps-in-scrolling {
|
||||
pointer-events: none; }
|
||||
.ps-theme-square.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-theme-square.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
|
||||
background-color: #999; }
|
||||
.ps-theme-square.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-theme-square.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
|
||||
background-color: #999; }
|
||||
.ps-theme-square > .ps-scrollbar-x-rail {
|
||||
display: none;
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
opacity: 0;
|
||||
transition: background-color .2s linear, opacity .2s linear;
|
||||
bottom: 0;
|
||||
/* there must be 'bottom' for ps-scrollbar-x-rail */
|
||||
height: 10px; }
|
||||
.ps-theme-square > .ps-scrollbar-x-rail > .ps-scrollbar-x {
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
background-color: #aaa;
|
||||
border-radius: 0;
|
||||
transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;
|
||||
bottom: 0;
|
||||
/* there must be 'bottom' for ps-scrollbar-x */
|
||||
height: 10px; }
|
||||
.ps-theme-square > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x, .ps-theme-square > .ps-scrollbar-x-rail:active > .ps-scrollbar-x {
|
||||
height: 10px; }
|
||||
.ps-theme-square > .ps-scrollbar-y-rail {
|
||||
display: none;
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
opacity: 0;
|
||||
transition: background-color .2s linear, opacity .2s linear;
|
||||
right: 0;
|
||||
/* there must be 'right' for ps-scrollbar-y-rail */
|
||||
width: 10px; }
|
||||
.ps-theme-square > .ps-scrollbar-y-rail > .ps-scrollbar-y {
|
||||
position: absolute;
|
||||
/* please don't change 'position' */
|
||||
background-color: #aaa;
|
||||
border-radius: 0;
|
||||
transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;
|
||||
right: 0;
|
||||
/* there must be 'right' for ps-scrollbar-y */
|
||||
width: 10px; }
|
||||
.ps-theme-square > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y, .ps-theme-square > .ps-scrollbar-y-rail:active > .ps-scrollbar-y {
|
||||
width: 10px; }
|
||||
.ps-theme-square:hover.ps-in-scrolling {
|
||||
pointer-events: none; }
|
||||
.ps-theme-square:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-theme-square:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
|
||||
background-color: #999; }
|
||||
.ps-theme-square:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-theme-square:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
|
||||
background-color: #999; }
|
||||
.ps-theme-square:hover > .ps-scrollbar-x-rail,
|
||||
.ps-theme-square:hover > .ps-scrollbar-y-rail {
|
||||
opacity: 0.6; }
|
||||
.ps-theme-square:hover > .ps-scrollbar-x-rail:hover {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-theme-square:hover > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x {
|
||||
background-color: #999; }
|
||||
.ps-theme-square:hover > .ps-scrollbar-y-rail:hover {
|
||||
background-color: #eee;
|
||||
opacity: 0.9; }
|
||||
.ps-theme-square:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y {
|
||||
background-color: #999; }
|
||||
@@ -3,25 +3,36 @@
|
||||
<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">
|
||||
<link href="custom-theme.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 { position: relative; margin:0px auto; padding:0px; width: 600px; height: 400px; overflow: hidden; }
|
||||
.contentHolder .content { background-image: url('./azusa.jpg'); width: 1280px; height: 720px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="Default" class="contentHolder">
|
||||
<div id="container" class="contentHolder">
|
||||
<div class="content">
|
||||
</div>
|
||||
</div>
|
||||
<p style='text-align: center'>
|
||||
<button id='default'>default</button>
|
||||
<button id='custom'>custom</button>
|
||||
</p>
|
||||
<script>
|
||||
var $ = document.querySelector.bind(document);
|
||||
var container = $('#container');
|
||||
window.onload = function () {
|
||||
Ps.initialize($('#Default'), {
|
||||
theme: 'big-and-ugly'
|
||||
});
|
||||
Ps.initialize(container, { theme: 'square' });
|
||||
};
|
||||
$('#default').addEventListener('click', function () {
|
||||
Ps.destroy(container);
|
||||
Ps.initialize(container);
|
||||
});
|
||||
$('#custom').addEventListener('click', function () {
|
||||
Ps.destroy(container);
|
||||
Ps.initialize(container, { theme: 'square' });
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
23
examples/custom-theme.scss
Normal file
23
examples/custom-theme.scss
Normal file
@@ -0,0 +1,23 @@
|
||||
@import '../src/css/main';
|
||||
|
||||
/*
|
||||
this file is built into custom-theme.css
|
||||
|
||||
$ node-sass examples/custom-theme.scss -o examples/
|
||||
*/
|
||||
|
||||
.ps-theme-square {
|
||||
@include ps-container(map-merge($ps-theme-default, (
|
||||
border-radius: 0,
|
||||
scrollbar-x-rail-bottom: 0,
|
||||
scrollbar-x-rail-height: 10px,
|
||||
scrollbar-x-bottom: 0,
|
||||
scrollbar-x-height: 10px,
|
||||
scrollbar-x-hover-height: 10px,
|
||||
scrollbar-y-rail-right: 0,
|
||||
scrollbar-y-rail-width: 10px,
|
||||
scrollbar-y-right: 0,
|
||||
scrollbar-y-width: 10px,
|
||||
scrollbar-y-hover-width: 10px,
|
||||
)));
|
||||
}
|
||||
@@ -38,10 +38,11 @@
|
||||
|
||||
<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');
|
||||
var container = document.querySelector('.container');
|
||||
var axis = document.getElementById('axis');
|
||||
var direction = document.getElementById('direction');
|
||||
var startEnd = document.getElementById('start-end');
|
||||
|
||||
Ps.initialize(container);
|
||||
|
||||
document.addEventListener('ps-scroll-y', function () {
|
||||
@@ -83,7 +84,6 @@
|
||||
document.addEventListener('ps-x-reach-end', function () {
|
||||
startEnd.innerHTML = 'Reached end of <em>X-Axis</em>'
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
63
examples/infinite-scroll.html
Normal file
63
examples/infinite-scroll.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>perfect-scrollbar example</title>
|
||||
<link href="../dist/css/perfect-scrollbar.css" rel="stylesheet">
|
||||
<script src="../dist/js/perfect-scrollbar.js"></script>
|
||||
<style>
|
||||
#Default {
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
background-color: #f1f1f1;
|
||||
border: 1px solid blue;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
}
|
||||
.entryPlaceholder {
|
||||
height: 48px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="Default">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var x = 0;
|
||||
var $ = document.querySelector.bind(document);
|
||||
window.onload = function () {
|
||||
// show some initial data
|
||||
for(var i = 0; i < 10; i++) {
|
||||
$('#Default').innerHTML += '<div class="entryPlaceholder">Entry #' + (x++) + '</div>';
|
||||
}
|
||||
Ps.initialize($('#Default'));
|
||||
|
||||
};
|
||||
|
||||
var isProgramaticallyTriggered = false;
|
||||
var addEntries = function(num) {
|
||||
for(var i = 0; i < num; i++) {
|
||||
$('#Default').innerHTML += '<div class="entryPlaceholder">Entry #' + (x++) + '</div>';
|
||||
}
|
||||
|
||||
isProgramaticallyTriggered = true;
|
||||
Ps.update($('#Default'));
|
||||
isProgramaticallyTriggered = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// on scroll, add more entries
|
||||
document.addEventListener('ps-scroll-y', function(e) {
|
||||
if (!isProgramaticallyTriggered) {
|
||||
console.debug("user scrolled to pos: ", $('#Default').scrollTop);
|
||||
addEntries(1);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
55
examples/options-autoupdate.html
Normal file
55
examples/options-autoupdate.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>perfect-scrollbar example</title>
|
||||
<link href="../dist/css/perfect-scrollbar.css" rel="stylesheet">
|
||||
<script src="../dist/js/perfect-scrollbar.js"></script>
|
||||
<style>
|
||||
.contentHolder { position:relative; margin:0px auto; padding:0px; width: 80%; height: 400px; overflow: auto; }
|
||||
.always-visible.contentHolder .content { background-image: url('./azusa.jpg'); width: 680px; height: 320px; }
|
||||
.spacer { text-align:center }
|
||||
|
||||
.always-visible.ps-container > .ps-scrollbar-x-rail,
|
||||
.always-visible.ps-container > .ps-scrollbar-y-rail {
|
||||
opacity: 0.6;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="Default" class="contentHolder always-visible">
|
||||
<div id="Content" class="content">
|
||||
</div>
|
||||
</div>
|
||||
<p style='text-align: center'>
|
||||
<button onclick='addContent()'>Add new content!</button>
|
||||
<button onclick='removeContent()'>Remove content!</button>
|
||||
</p>
|
||||
<script>
|
||||
var i = 1;
|
||||
var $ = document.querySelector.bind(document);
|
||||
window.onload = function () {
|
||||
Ps.initialize($('#Default'), {
|
||||
autoupdate: true
|
||||
});
|
||||
};
|
||||
|
||||
var addContent = function () {
|
||||
var newDiv = document.createElement('div');
|
||||
newDiv.id = 'node' + i++;
|
||||
var newContent = document.createTextNode('Hi there!');
|
||||
newDiv.appendChild(newContent);
|
||||
|
||||
$('#Default').insertBefore(newDiv, $('#Content'));
|
||||
};
|
||||
|
||||
var removeContent = function () {
|
||||
if (i <= 1) return;
|
||||
|
||||
var node = $('#node' + --i);
|
||||
node.parentNode.removeChild(node);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
49
examples/options-handlers.html
Normal file
49
examples/options-handlers.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>perfect-scrollbar example</title>
|
||||
<link href="../dist/css/perfect-scrollbar.css" rel="stylesheet">
|
||||
<script src="../dist/js/perfect-scrollbar.js"></script>
|
||||
<style>
|
||||
.contentHolder { position:relative; padding:0px; width: 600px; height: 400px; overflow: auto; }
|
||||
.contentHolder .content { background-image: url('./azusa.jpg'); width: 1280px; height: 720px; }
|
||||
.spacer { text-align:center }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Default</h1>
|
||||
<pre><code>handlers: ['click-rail', 'drag-scrollbar', 'keyboard', 'wheel', 'touch']</code></pre>
|
||||
<div id="default" class="contentHolder">
|
||||
<div class="content">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>No keyboard</h1>
|
||||
<pre><code>handlers: ['click-rail', 'drag-scrollbar', 'wheel', 'touch']</code></pre>
|
||||
<div id="no-keyboard" class="contentHolder">
|
||||
<div class="content">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Click and Drag</h1>
|
||||
<pre><code>handlers: ['click-rail', 'drag-scrollbar']</code></pre>
|
||||
<div id="click-and-drag" class="contentHolder">
|
||||
<div class="content">
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var $ = document.querySelector.bind(document);
|
||||
window.onload = function () {
|
||||
Ps.initialize($('#default'));
|
||||
Ps.initialize($('#no-keyboard'), {
|
||||
handlers: ['click-rail', 'drag-scrollbar', 'wheel', 'touch']
|
||||
});
|
||||
Ps.initialize($('#click-and-drag'), {
|
||||
handlers: ['click-rail', 'drag-scrollbar']
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
34
gulpfile.js
34
gulpfile.js
@@ -1,20 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp')
|
||||
, browserify = require('browserify')
|
||||
, 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')
|
||||
, sass = require('gulp-sass')
|
||||
, source = require('vinyl-source-stream')
|
||||
, stream = require('event-stream')
|
||||
, uglify = require('gulp-uglify')
|
||||
, autoprefixer = require('gulp-autoprefixer')
|
||||
, zip = require('gulp-zip');
|
||||
var autoprefixer = require('gulp-autoprefixer');
|
||||
var browserify = require('browserify');
|
||||
var buffer = require('vinyl-buffer');
|
||||
var connect = require('gulp-connect');
|
||||
var del = require('del');
|
||||
var eslint = require('gulp-eslint');
|
||||
var gulp = require('gulp');
|
||||
var insert = require('gulp-insert');
|
||||
var path = require('path');
|
||||
var rename = require('gulp-rename');
|
||||
var sass = require('gulp-sass');
|
||||
var source = require('vinyl-source-stream');
|
||||
var stream = require('event-stream');
|
||||
var uglify = require('gulp-uglify');
|
||||
var zip = require('gulp-zip');
|
||||
|
||||
var version = '/* perfect-scrollbar v' + require('./package').version + ' */\n';
|
||||
|
||||
@@ -30,7 +30,7 @@ gulp.task('clean:js', function () {
|
||||
});
|
||||
|
||||
gulp.task('clean:js:min', function () {
|
||||
return del(['./dist/js/min/*.js']);
|
||||
return del(['./dist/js/*.min.js']);
|
||||
});
|
||||
|
||||
var jsEntries = [
|
||||
@@ -76,7 +76,7 @@ gulp.task('js:min', ['clean:js:min'], function () {
|
||||
path.basename = 'perfect-scrollbar.' + path.basename + '.min';
|
||||
}
|
||||
}))
|
||||
.pipe(gulp.dest('./dist/js/min'))
|
||||
.pipe(gulp.dest('./dist/js'))
|
||||
.pipe(connect.reload());
|
||||
});
|
||||
return stream.merge.apply(null, tasks);
|
||||
|
||||
24
package.json
24
package.json
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "perfect-scrollbar",
|
||||
"version": "0.6.9",
|
||||
"version": "0.6.17",
|
||||
"description": "Minimalistic but perfect custom scrollbar plugin",
|
||||
"author": "Hyunje Alex Jun <me@noraesae.net>",
|
||||
"author": "Hyunje Jun <me@noraesae.net>",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Hyunje Alex Jun",
|
||||
"name": "Hyunje Jun",
|
||||
"email": "me@noraesae.net"
|
||||
}
|
||||
],
|
||||
@@ -26,6 +26,13 @@
|
||||
"engines": {
|
||||
"node": ">= 0.12.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"src",
|
||||
"index.js",
|
||||
"jquery.js",
|
||||
"perfect-scrollbar.d.ts"
|
||||
],
|
||||
"devDependencies": {
|
||||
"browserify": "^11.2.0",
|
||||
"del": "^2.0.2",
|
||||
@@ -42,10 +49,19 @@
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0"
|
||||
},
|
||||
"jspm": {
|
||||
"main": "./index.js",
|
||||
"registry": "jspm"
|
||||
},
|
||||
"typings": "perfect-scrollbar.d.ts",
|
||||
"scripts": {
|
||||
"test": "gulp",
|
||||
"before-deploy": "gulp && gulp compress",
|
||||
"release": "rm -rf dist && gulp && npm publish"
|
||||
"release": "rm -rf dist && gulp && npm publish",
|
||||
"bump": "npm version patch",
|
||||
"bump:major": "npm version major",
|
||||
"bump:minor": "npm version minor",
|
||||
"postversion": "git push origin master --follow-tags"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
29
perfect-scrollbar.d.ts
vendored
Normal file
29
perfect-scrollbar.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
interface PerfectScrollbarOptions {
|
||||
wheelSpeed?: number;
|
||||
wheelPropagation?: boolean;
|
||||
swipePropagation?: boolean;
|
||||
minScrollbarLength?: number;
|
||||
maxScrollbarLength?: number;
|
||||
useBothWheelAxes?: boolean;
|
||||
useKeyboard?: boolean;
|
||||
suppressScrollX?: boolean;
|
||||
suppressScrollY?: boolean;
|
||||
scrollXMarginOffset?: number;
|
||||
scrollYMarginOffset?: number;
|
||||
}
|
||||
|
||||
interface PerfectScrollbar {
|
||||
initialize(container: HTMLElement, options?: PerfectScrollbarOptions): void;
|
||||
update(container: HTMLElement): void;
|
||||
destroy(container: HTMLElement): void;
|
||||
}
|
||||
|
||||
interface JQuery {
|
||||
perfectScrollbar(options?: PerfectScrollbarOptions): JQuery;
|
||||
}
|
||||
|
||||
declare var ps: PerfectScrollbar;
|
||||
|
||||
declare module "perfect-scrollbar" {
|
||||
export = ps;
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
@mixin scrollbar-rail-default($theme) {
|
||||
display: none;
|
||||
position: absolute; /* please don't change 'position' */
|
||||
border-radius: map_get($theme, border-radius);
|
||||
opacity: map_get($theme, rail-default-opacity);
|
||||
transition: background-color .2s linear, opacity .2s linear;
|
||||
}
|
||||
@@ -15,7 +14,8 @@
|
||||
position: absolute; /* please don't change 'position' */
|
||||
background-color: map_get($theme, bar-container-hover-bg);
|
||||
border-radius: map_get($theme, border-radius);
|
||||
transition: background-color .2s linear;
|
||||
transition: background-color .2s linear, height .2s linear, width .2s ease-in-out,
|
||||
border-radius .2s ease-in-out;
|
||||
}
|
||||
|
||||
@mixin scrollbar-hover($theme) {
|
||||
@@ -24,17 +24,18 @@
|
||||
|
||||
@mixin in-scrolling($theme) {
|
||||
&.ps-in-scrolling {
|
||||
pointer-events: none;
|
||||
&.ps-x > .ps-scrollbar-x-rail {
|
||||
@include scrollbar-rail-hover($theme);
|
||||
> .ps-scrollbar-x {
|
||||
@include scrollbar-hover($theme);
|
||||
height: map_get($theme, scrollbar-x-hover-height);
|
||||
}
|
||||
}
|
||||
&.ps-y > .ps-scrollbar-y-rail {
|
||||
@include scrollbar-rail-hover($theme);
|
||||
> .ps-scrollbar-y {
|
||||
@include scrollbar-hover($theme);
|
||||
width: map_get($theme, scrollbar-y-hover-width);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,8 +43,19 @@
|
||||
|
||||
// Layout and theme mixin
|
||||
@mixin ps-container($theme) {
|
||||
-ms-touch-action: none;
|
||||
-ms-touch-action: auto;
|
||||
touch-action: auto;
|
||||
overflow: hidden !important;
|
||||
-ms-overflow-style: none;
|
||||
|
||||
// Edge
|
||||
@supports (-ms-overflow-style: none) {
|
||||
overflow: auto !important;
|
||||
}
|
||||
// IE10+
|
||||
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
&.ps-active-x > .ps-scrollbar-x-rail,
|
||||
&.ps-active-y > .ps-scrollbar-y-rail {
|
||||
@@ -63,6 +75,12 @@
|
||||
bottom: map_get($theme, scrollbar-x-bottom); /* there must be 'bottom' for ps-scrollbar-x */
|
||||
height: map_get($theme, scrollbar-x-height);
|
||||
}
|
||||
&:hover,
|
||||
&:active {
|
||||
> .ps-scrollbar-x {
|
||||
height: map_get($theme, scrollbar-x-hover-height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .ps-scrollbar-y-rail {
|
||||
@@ -75,6 +93,12 @@
|
||||
right: map_get($theme, scrollbar-y-right); /* there must be 'right' for ps-scrollbar-y */
|
||||
width: map_get($theme, scrollbar-y-width);
|
||||
}
|
||||
&:hover,
|
||||
&:active {
|
||||
> .ps-scrollbar-y {
|
||||
width: map_get($theme, scrollbar-y-hover-width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
||||
@@ -11,10 +11,12 @@ $ps-theme-default: (
|
||||
scrollbar-x-rail-height: $ps-scrollbar-x-rail-height,
|
||||
scrollbar-x-bottom: $ps-scrollbar-x-bottom,
|
||||
scrollbar-x-height: $ps-scrollbar-x-height,
|
||||
scrollbar-x-hover-height: $ps-scrollbar-x-hover-height,
|
||||
scrollbar-y-rail-right: $ps-scrollbar-y-rail-right,
|
||||
scrollbar-y-rail-width: $ps-scrollbar-y-rail-width,
|
||||
scrollbar-y-right: $ps-scrollbar-y-right,
|
||||
scrollbar-y-width: $ps-scrollbar-y-width,
|
||||
scrollbar-y-hover-width: $ps-scrollbar-y-hover-width,
|
||||
);
|
||||
|
||||
// Default theme
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Colors
|
||||
$ps-border-radius: 4px !default;
|
||||
$ps-border-radius: 6px !default;
|
||||
|
||||
$ps-rail-default-opacity: 0 !default;
|
||||
$ps-rail-container-hover-opacity: 0.6 !default;
|
||||
@@ -11,12 +11,14 @@ $ps-bar-hover-bg: #999 !default;
|
||||
$ps-rail-hover-bg: #eee !default;
|
||||
|
||||
// Sizes
|
||||
$ps-scrollbar-x-rail-bottom: 3px !default;
|
||||
$ps-scrollbar-x-rail-height: 8px !default;
|
||||
$ps-scrollbar-x-bottom: 0 !default;
|
||||
$ps-scrollbar-x-height: 8px !default;
|
||||
$ps-scrollbar-x-rail-bottom: 0px !default;
|
||||
$ps-scrollbar-x-rail-height: 15px !default;
|
||||
$ps-scrollbar-x-bottom: 2px !default;
|
||||
$ps-scrollbar-x-height: 6px !default;
|
||||
$ps-scrollbar-x-hover-height: 11px !default;
|
||||
|
||||
$ps-scrollbar-y-rail-right: 3px !default;
|
||||
$ps-scrollbar-y-rail-width: 8px !default;
|
||||
$ps-scrollbar-y-right: 0 !default;
|
||||
$ps-scrollbar-y-width: 8px !default;
|
||||
$ps-scrollbar-y-rail-right: 0 !default;
|
||||
$ps-scrollbar-y-rail-width: 15px !default;
|
||||
$ps-scrollbar-y-right: 2px !default;
|
||||
$ps-scrollbar-y-width: 6px !default;
|
||||
$ps-scrollbar-y-hover-width: 11px !default;
|
||||
|
||||
6
src/js/adaptor/jquery.js
vendored
6
src/js/adaptor/jquery.js
vendored
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var ps = require('../main')
|
||||
, psInstances = require('../plugin/instances');
|
||||
var ps = require('../main');
|
||||
var psInstances = require('../plugin/instances');
|
||||
|
||||
function mountJQuery(jQuery) {
|
||||
jQuery.fn.perfectScrollbar = function (settingOrCommand) {
|
||||
@@ -24,8 +24,6 @@ function mountJQuery(jQuery) {
|
||||
ps.destroy(this);
|
||||
}
|
||||
}
|
||||
|
||||
return jQuery(this);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@ DOM.appendTo = function (child, parent) {
|
||||
};
|
||||
|
||||
function cssGet(element, styleName) {
|
||||
return window.getComputedStyle(element)[styleName];
|
||||
var style = window.getComputedStyle(element);
|
||||
return style
|
||||
? style[styleName]
|
||||
: null;
|
||||
}
|
||||
|
||||
function cssSet(element, styleName, styleValue) {
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
var cls = require('./class')
|
||||
, d = require('./dom');
|
||||
var cls = require('./class');
|
||||
var dom = require('./dom');
|
||||
|
||||
exports.toInt = function (x) {
|
||||
var toInt = exports.toInt = function (x) {
|
||||
return parseInt(x, 10) || 0;
|
||||
};
|
||||
|
||||
exports.clone = function (obj) {
|
||||
if (obj === null) {
|
||||
var clone = exports.clone = function (obj) {
|
||||
if (!obj) {
|
||||
return null;
|
||||
} else if (Array.isArray(obj)) {
|
||||
return obj.map(clone);
|
||||
} else if (typeof obj === 'object') {
|
||||
var result = {};
|
||||
for (var key in obj) {
|
||||
result[key] = this.clone(obj[key]);
|
||||
result[key] = clone(obj[key]);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
@@ -21,19 +23,39 @@ exports.clone = function (obj) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.debounce = function (func, wait, immediate) {
|
||||
var timeout;
|
||||
return function () {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
var later = function () {
|
||||
timeout = null;
|
||||
if (!immediate) {
|
||||
func.apply(context, args);
|
||||
}
|
||||
};
|
||||
var callNow = immediate && !timeout;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
if (callNow) {
|
||||
func.apply(context, args);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.extend = function (original, source) {
|
||||
var result = this.clone(original);
|
||||
var result = clone(original);
|
||||
for (var key in source) {
|
||||
result[key] = this.clone(source[key]);
|
||||
result[key] = clone(source[key]);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
exports.isEditable = function (el) {
|
||||
return d.matches(el, "input,[contenteditable]") ||
|
||||
d.matches(el, "select,[contenteditable]") ||
|
||||
d.matches(el, "textarea,[contenteditable]") ||
|
||||
d.matches(el, "button,[contenteditable]");
|
||||
return dom.matches(el, "input,[contenteditable]") ||
|
||||
dom.matches(el, "select,[contenteditable]") ||
|
||||
dom.matches(el, "textarea,[contenteditable]") ||
|
||||
dom.matches(el, "button,[contenteditable]");
|
||||
};
|
||||
|
||||
exports.removePsClasses = function (element) {
|
||||
@@ -47,11 +69,11 @@ exports.removePsClasses = function (element) {
|
||||
};
|
||||
|
||||
exports.outerWidth = function (element) {
|
||||
return this.toInt(d.css(element, 'width')) +
|
||||
this.toInt(d.css(element, 'paddingLeft')) +
|
||||
this.toInt(d.css(element, 'paddingRight')) +
|
||||
this.toInt(d.css(element, 'borderLeftWidth')) +
|
||||
this.toInt(d.css(element, 'borderRightWidth'));
|
||||
return toInt(dom.css(element, 'width')) +
|
||||
toInt(dom.css(element, 'paddingLeft')) +
|
||||
toInt(dom.css(element, 'paddingRight')) +
|
||||
toInt(dom.css(element, 'borderLeftWidth')) +
|
||||
toInt(dom.css(element, 'borderRightWidth'));
|
||||
};
|
||||
|
||||
exports.startScrolling = function (element, axis) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var destroy = require('./plugin/destroy')
|
||||
, initialize = require('./plugin/initialize')
|
||||
, update = require('./plugin/update');
|
||||
var destroy = require('./plugin/destroy');
|
||||
var initialize = require('./plugin/initialize');
|
||||
var update = require('./plugin/update');
|
||||
|
||||
module.exports = {
|
||||
initialize: initialize,
|
||||
|
||||
30
src/js/plugin/autoupdate.js
Normal file
30
src/js/plugin/autoupdate.js
Normal file
@@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
var update = require('./update');
|
||||
var MutationObserver = window.MutationObserver;
|
||||
var instances = require('./instances');
|
||||
|
||||
var createDOMEvent = function (name) {
|
||||
var event = document.createEvent('Event');
|
||||
event.initEvent(name, true, true);
|
||||
return event;
|
||||
};
|
||||
|
||||
module.exports = function (element) {
|
||||
if (MutationObserver === null || MutationObserver === undefined) {
|
||||
// MutationObserver is not supported
|
||||
return;
|
||||
}
|
||||
|
||||
var i = instances.get(element);
|
||||
var onMutationObserver = function () {
|
||||
update(element);
|
||||
element.dispatchEvent(createDOMEvent('ps-dom-change'));
|
||||
};
|
||||
|
||||
i.observer = new MutationObserver(onMutationObserver);
|
||||
onMutationObserver();
|
||||
|
||||
var config = { childList: true, subtree: true };
|
||||
i.observer.observe(element, config);
|
||||
};
|
||||
@@ -1,18 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
handlers: ['click-rail', 'drag-scrollbar', 'keyboard', 'wheel', 'touch'],
|
||||
maxScrollbarLength: null,
|
||||
minScrollbarLength: null,
|
||||
scrollXMarginOffset: 0,
|
||||
scrollYMarginOffset: 0,
|
||||
stopPropagationOnClick: true,
|
||||
suppressScrollX: false,
|
||||
suppressScrollY: false,
|
||||
swipePropagation: true,
|
||||
useBothWheelAxes: false,
|
||||
useKeyboard: true,
|
||||
useSelectionScroll: false,
|
||||
wheelPropagation: false,
|
||||
wheelSpeed: 1,
|
||||
theme: 'default'
|
||||
theme: 'default',
|
||||
autoupdate: true
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var d = require('../lib/dom')
|
||||
, h = require('../lib/helper')
|
||||
, instances = require('./instances');
|
||||
var _ = require('../lib/helper');
|
||||
var dom = require('../lib/dom');
|
||||
var instances = require('./instances');
|
||||
|
||||
module.exports = function (element) {
|
||||
var i = instances.get(element);
|
||||
@@ -11,12 +11,16 @@ module.exports = function (element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (i.observer) {
|
||||
i.observer.disconnect();
|
||||
}
|
||||
|
||||
i.event.unbindAll();
|
||||
d.remove(i.scrollbarX);
|
||||
d.remove(i.scrollbarY);
|
||||
d.remove(i.scrollbarXRail);
|
||||
d.remove(i.scrollbarYRail);
|
||||
h.removePsClasses(element);
|
||||
dom.remove(i.scrollbarX);
|
||||
dom.remove(i.scrollbarY);
|
||||
dom.remove(i.scrollbarXRail);
|
||||
dom.remove(i.scrollbarYRail);
|
||||
_.removePsClasses(element);
|
||||
|
||||
instances.remove(element);
|
||||
};
|
||||
|
||||
@@ -1,53 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
var h = require('../../lib/helper')
|
||||
, instances = require('../instances')
|
||||
, updateGeometry = require('../update-geometry')
|
||||
, updateScroll = require('../update-scroll');
|
||||
var instances = require('../instances');
|
||||
var updateGeometry = require('../update-geometry');
|
||||
var updateScroll = require('../update-scroll');
|
||||
|
||||
function bindClickRailHandler(element, i) {
|
||||
function pageOffset(el) {
|
||||
return el.getBoundingClientRect();
|
||||
}
|
||||
var stopPropagation = window.Event.prototype.stopPropagation.bind;
|
||||
var stopPropagation = function (e) { e.stopPropagation(); };
|
||||
|
||||
if (i.settings.stopPropagationOnClick) {
|
||||
i.event.bind(i.scrollbarY, 'click', stopPropagation);
|
||||
}
|
||||
i.event.bind(i.scrollbarY, 'click', stopPropagation);
|
||||
i.event.bind(i.scrollbarYRail, 'click', function (e) {
|
||||
var halfOfScrollbarLength = h.toInt(i.scrollbarYHeight / 2);
|
||||
var positionTop = i.railYRatio * (e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top - halfOfScrollbarLength);
|
||||
var maxPositionTop = i.railYRatio * (i.railYHeight - i.scrollbarYHeight);
|
||||
var positionRatio = positionTop / maxPositionTop;
|
||||
var positionTop = e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top;
|
||||
var direction = positionTop > i.scrollbarYTop ? 1 : -1;
|
||||
|
||||
if (positionRatio < 0) {
|
||||
positionRatio = 0;
|
||||
} else if (positionRatio > 1) {
|
||||
positionRatio = 1;
|
||||
}
|
||||
|
||||
updateScroll(element, 'top', (i.contentHeight - i.containerHeight) * positionRatio);
|
||||
updateScroll(element, 'top', element.scrollTop + direction * i.containerHeight);
|
||||
updateGeometry(element);
|
||||
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
if (i.settings.stopPropagationOnClick) {
|
||||
i.event.bind(i.scrollbarX, 'click', stopPropagation);
|
||||
}
|
||||
i.event.bind(i.scrollbarX, 'click', stopPropagation);
|
||||
i.event.bind(i.scrollbarXRail, 'click', function (e) {
|
||||
var halfOfScrollbarLength = h.toInt(i.scrollbarXWidth / 2);
|
||||
var positionLeft = i.railXRatio * (e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength);
|
||||
var maxPositionLeft = i.railXRatio * (i.railXWidth - i.scrollbarXWidth);
|
||||
var positionRatio = positionLeft / maxPositionLeft;
|
||||
var positionLeft = e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left;
|
||||
var direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
|
||||
|
||||
if (positionRatio < 0) {
|
||||
positionRatio = 0;
|
||||
} else if (positionRatio > 1) {
|
||||
positionRatio = 1;
|
||||
}
|
||||
|
||||
updateScroll(element, 'left', ((i.contentWidth - i.containerWidth) * positionRatio) - i.negativeScrollAdjustment);
|
||||
updateScroll(element, 'left', element.scrollLeft + direction * i.containerWidth);
|
||||
updateGeometry(element);
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
var d = require('../../lib/dom')
|
||||
, h = require('../../lib/helper')
|
||||
, instances = require('../instances')
|
||||
, updateGeometry = require('../update-geometry')
|
||||
, updateScroll = require('../update-scroll');
|
||||
var _ = require('../../lib/helper');
|
||||
var dom = require('../../lib/dom');
|
||||
var instances = require('../instances');
|
||||
var updateGeometry = require('../update-geometry');
|
||||
var updateScroll = require('../update-scroll');
|
||||
|
||||
function bindMouseScrollXHandler(element, i) {
|
||||
var currentLeft = null;
|
||||
@@ -22,7 +22,7 @@ function bindMouseScrollXHandler(element, i) {
|
||||
i.scrollbarXLeft = newLeft;
|
||||
}
|
||||
|
||||
var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
|
||||
var scrollLeft = _.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
|
||||
updateScroll(element, 'left', scrollLeft);
|
||||
}
|
||||
|
||||
@@ -34,14 +34,14 @@ function bindMouseScrollXHandler(element, i) {
|
||||
};
|
||||
|
||||
var mouseUpHandler = function () {
|
||||
h.stopScrolling(element, 'x');
|
||||
_.stopScrolling(element, 'x');
|
||||
i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
|
||||
};
|
||||
|
||||
i.event.bind(i.scrollbarX, 'mousedown', function (e) {
|
||||
currentPageX = e.pageX;
|
||||
currentLeft = h.toInt(d.css(i.scrollbarX, 'left')) * i.railXRatio;
|
||||
h.startScrolling(element, 'x');
|
||||
currentLeft = _.toInt(dom.css(i.scrollbarX, 'left')) * i.railXRatio;
|
||||
_.startScrolling(element, 'x');
|
||||
|
||||
i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
|
||||
i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
|
||||
@@ -67,7 +67,7 @@ function bindMouseScrollYHandler(element, i) {
|
||||
i.scrollbarYTop = newTop;
|
||||
}
|
||||
|
||||
var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
|
||||
var scrollTop = _.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
|
||||
updateScroll(element, 'top', scrollTop);
|
||||
}
|
||||
|
||||
@@ -79,14 +79,14 @@ function bindMouseScrollYHandler(element, i) {
|
||||
};
|
||||
|
||||
var mouseUpHandler = function () {
|
||||
h.stopScrolling(element, 'y');
|
||||
_.stopScrolling(element, 'y');
|
||||
i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
|
||||
};
|
||||
|
||||
i.event.bind(i.scrollbarY, 'mousedown', function (e) {
|
||||
currentPageY = e.pageY;
|
||||
currentTop = h.toInt(d.css(i.scrollbarY, 'top')) * i.railYRatio;
|
||||
h.startScrolling(element, 'y');
|
||||
currentTop = _.toInt(dom.css(i.scrollbarY, 'top')) * i.railYRatio;
|
||||
_.startScrolling(element, 'y');
|
||||
|
||||
i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
|
||||
i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
var h = require('../../lib/helper')
|
||||
, d = require('../../lib/dom')
|
||||
, instances = require('../instances')
|
||||
, updateGeometry = require('../update-geometry')
|
||||
, updateScroll = require('../update-scroll');
|
||||
var _ = require('../../lib/helper');
|
||||
var dom = require('../../lib/dom');
|
||||
var instances = require('../instances');
|
||||
var updateGeometry = require('../update-geometry');
|
||||
var updateScroll = require('../update-scroll');
|
||||
|
||||
function bindKeyboardHandler(element, i) {
|
||||
var hovered = false;
|
||||
@@ -40,12 +40,12 @@ function bindKeyboardHandler(element, i) {
|
||||
}
|
||||
|
||||
i.event.bind(i.ownerDocument, 'keydown', function (e) {
|
||||
if (e.isDefaultPrevented && e.isDefaultPrevented()) {
|
||||
if ((e.isDefaultPrevented && e.isDefaultPrevented()) || e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
var focused = d.matches(i.scrollbarX, ':focus') ||
|
||||
d.matches(i.scrollbarY, ':focus');
|
||||
var focused = dom.matches(i.scrollbarX, ':focus') ||
|
||||
dom.matches(i.scrollbarY, ':focus');
|
||||
|
||||
if (!hovered && !focused) {
|
||||
return;
|
||||
@@ -53,11 +53,15 @@ function bindKeyboardHandler(element, i) {
|
||||
|
||||
var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement;
|
||||
if (activeElement) {
|
||||
// go deeper if element is a webcomponent
|
||||
while (activeElement.shadowRoot) {
|
||||
activeElement = activeElement.shadowRoot.activeElement;
|
||||
if (activeElement.tagName === 'IFRAME') {
|
||||
activeElement = activeElement.contentDocument.activeElement;
|
||||
} else {
|
||||
// go deeper if element is a webcomponent
|
||||
while (activeElement.shadowRoot) {
|
||||
activeElement = activeElement.shadowRoot.activeElement;
|
||||
}
|
||||
}
|
||||
if (h.isEditable(activeElement)) {
|
||||
if (_.isEditable(activeElement)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -67,16 +71,40 @@ function bindKeyboardHandler(element, i) {
|
||||
|
||||
switch (e.which) {
|
||||
case 37: // left
|
||||
deltaX = -30;
|
||||
if (e.metaKey) {
|
||||
deltaX = -i.contentWidth;
|
||||
} else if (e.altKey) {
|
||||
deltaX = -i.containerWidth;
|
||||
} else {
|
||||
deltaX = -30;
|
||||
}
|
||||
break;
|
||||
case 38: // up
|
||||
deltaY = 30;
|
||||
if (e.metaKey) {
|
||||
deltaY = i.contentHeight;
|
||||
} else if (e.altKey) {
|
||||
deltaY = i.containerHeight;
|
||||
} else {
|
||||
deltaY = 30;
|
||||
}
|
||||
break;
|
||||
case 39: // right
|
||||
deltaX = 30;
|
||||
if (e.metaKey) {
|
||||
deltaX = i.contentWidth;
|
||||
} else if (e.altKey) {
|
||||
deltaX = i.containerWidth;
|
||||
} else {
|
||||
deltaX = 30;
|
||||
}
|
||||
break;
|
||||
case 40: // down
|
||||
deltaY = -30;
|
||||
if (e.metaKey) {
|
||||
deltaY = -i.contentHeight;
|
||||
} else if (e.altKey) {
|
||||
deltaY = -i.containerHeight;
|
||||
} else {
|
||||
deltaY = -30;
|
||||
}
|
||||
break;
|
||||
case 33: // page up
|
||||
deltaY = 90;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var instances = require('../instances')
|
||||
, updateGeometry = require('../update-geometry')
|
||||
, updateScroll = require('../update-scroll');
|
||||
var instances = require('../instances');
|
||||
var updateGeometry = require('../update-geometry');
|
||||
var updateScroll = require('../update-scroll');
|
||||
|
||||
function bindMouseWheelHandler(element, i) {
|
||||
var shouldPrevent = false;
|
||||
@@ -52,23 +52,30 @@ function bindMouseWheelHandler(element, i) {
|
||||
deltaY = e.wheelDelta;
|
||||
}
|
||||
|
||||
if (e.shiftKey) {
|
||||
// reverse axis with shift key
|
||||
return [-deltaY, -deltaX];
|
||||
}
|
||||
return [deltaX, deltaY];
|
||||
}
|
||||
|
||||
function shouldBeConsumedByTextarea(deltaX, deltaY) {
|
||||
var hoveredTextarea = element.querySelector('textarea:hover');
|
||||
if (hoveredTextarea) {
|
||||
var maxScrollTop = hoveredTextarea.scrollHeight - hoveredTextarea.clientHeight;
|
||||
function shouldBeConsumedByChild(deltaX, deltaY) {
|
||||
var child = element.querySelector('textarea:hover, select[multiple]:hover, .ps-child:hover');
|
||||
if (child) {
|
||||
if (!window.getComputedStyle(child).overflow.match(/(scroll|auto)/)) {
|
||||
// if not scrollable
|
||||
return false;
|
||||
}
|
||||
|
||||
var maxScrollTop = child.scrollHeight - child.clientHeight;
|
||||
if (maxScrollTop > 0) {
|
||||
if (!(hoveredTextarea.scrollTop === 0 && deltaY > 0) &&
|
||||
!(hoveredTextarea.scrollTop === maxScrollTop && deltaY < 0)) {
|
||||
if (!(child.scrollTop === 0 && deltaY > 0) && !(child.scrollTop === maxScrollTop && deltaY < 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
var maxScrollLeft = hoveredTextarea.scrollLeft - hoveredTextarea.clientWidth;
|
||||
var maxScrollLeft = child.scrollLeft - child.clientWidth;
|
||||
if (maxScrollLeft > 0) {
|
||||
if (!(hoveredTextarea.scrollLeft === 0 && deltaX < 0) &&
|
||||
!(hoveredTextarea.scrollLeft === maxScrollLeft && deltaX > 0)) {
|
||||
if (!(child.scrollLeft === 0 && deltaX < 0) && !(child.scrollLeft === maxScrollLeft && deltaX > 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +89,7 @@ function bindMouseWheelHandler(element, i) {
|
||||
var deltaX = delta[0];
|
||||
var deltaY = delta[1];
|
||||
|
||||
if (shouldBeConsumedByTextarea(deltaX, deltaY)) {
|
||||
if (shouldBeConsumedByChild(deltaX, deltaY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var instances = require('../instances')
|
||||
, updateGeometry = require('../update-geometry');
|
||||
var instances = require('../instances');
|
||||
var updateGeometry = require('../update-geometry');
|
||||
|
||||
function bindNativeScrollHandler(element, i) {
|
||||
i.event.bind(element, 'scroll', function () {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var h = require('../../lib/helper')
|
||||
, instances = require('../instances')
|
||||
, updateGeometry = require('../update-geometry')
|
||||
, updateScroll = require('../update-scroll');
|
||||
var _ = require('../../lib/helper');
|
||||
var instances = require('../instances');
|
||||
var updateGeometry = require('../update-geometry');
|
||||
var updateScroll = require('../update-scroll');
|
||||
|
||||
function bindSelectionHandler(element, i) {
|
||||
function getRangeNode() {
|
||||
@@ -37,7 +37,7 @@ function bindSelectionHandler(element, i) {
|
||||
clearInterval(scrollingLoop);
|
||||
scrollingLoop = null;
|
||||
}
|
||||
h.stopScrolling(element);
|
||||
_.stopScrolling(element);
|
||||
}
|
||||
|
||||
var isSelected = false;
|
||||
@@ -55,6 +55,12 @@ function bindSelectionHandler(element, i) {
|
||||
stopScrolling();
|
||||
}
|
||||
});
|
||||
i.event.bind(window, 'keyup', function () {
|
||||
if (isSelected) {
|
||||
isSelected = false;
|
||||
stopScrolling();
|
||||
}
|
||||
});
|
||||
|
||||
i.event.bind(window, 'mousemove', function (e) {
|
||||
if (isSelected) {
|
||||
@@ -68,10 +74,10 @@ function bindSelectionHandler(element, i) {
|
||||
|
||||
if (mousePosition.x < containerGeometry.left + 3) {
|
||||
scrollDiff.left = -5;
|
||||
h.startScrolling(element, 'x');
|
||||
_.startScrolling(element, 'x');
|
||||
} else if (mousePosition.x > containerGeometry.right - 3) {
|
||||
scrollDiff.left = 5;
|
||||
h.startScrolling(element, 'x');
|
||||
_.startScrolling(element, 'x');
|
||||
} else {
|
||||
scrollDiff.left = 0;
|
||||
}
|
||||
@@ -82,14 +88,14 @@ function bindSelectionHandler(element, i) {
|
||||
} else {
|
||||
scrollDiff.top = -20;
|
||||
}
|
||||
h.startScrolling(element, 'y');
|
||||
_.startScrolling(element, 'y');
|
||||
} else if (mousePosition.y > containerGeometry.bottom - 3) {
|
||||
if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
|
||||
scrollDiff.top = 5;
|
||||
} else {
|
||||
scrollDiff.top = 20;
|
||||
}
|
||||
h.startScrolling(element, 'y');
|
||||
_.startScrolling(element, 'y');
|
||||
} else {
|
||||
scrollDiff.top = 0;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var instances = require('../instances')
|
||||
, updateGeometry = require('../update-geometry')
|
||||
, updateScroll = require('../update-scroll');
|
||||
var _ = require('../../lib/helper');
|
||||
var instances = require('../instances');
|
||||
var updateGeometry = require('../update-geometry');
|
||||
var updateScroll = require('../update-scroll');
|
||||
|
||||
function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
|
||||
function shouldPreventDefault(deltaX, deltaY) {
|
||||
@@ -87,29 +88,37 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
|
||||
}
|
||||
}
|
||||
function touchMove(e) {
|
||||
if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
|
||||
var touch = getTouch(e);
|
||||
var target = e.target;
|
||||
var className = target && target.getAttribute && target.getAttribute('class') || '';
|
||||
|
||||
var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
|
||||
|
||||
var differenceX = currentOffset.pageX - startOffset.pageX;
|
||||
var differenceY = currentOffset.pageY - startOffset.pageY;
|
||||
|
||||
applyTouchMove(differenceX, differenceY);
|
||||
startOffset = currentOffset;
|
||||
|
||||
var currentTime = (new Date()).getTime();
|
||||
|
||||
var timeGap = currentTime - startTime;
|
||||
if (timeGap > 0) {
|
||||
speed.x = differenceX / timeGap;
|
||||
speed.y = differenceY / timeGap;
|
||||
startTime = currentTime;
|
||||
if (!className.match(/ps-prevent-touchmove/)) {
|
||||
if (!inLocalTouch && i.settings.swipePropagation) {
|
||||
touchStart(e);
|
||||
}
|
||||
if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
|
||||
var touch = getTouch(e);
|
||||
|
||||
if (shouldPreventDefault(differenceX, differenceY)) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
|
||||
|
||||
var differenceX = currentOffset.pageX - startOffset.pageX;
|
||||
var differenceY = currentOffset.pageY - startOffset.pageY;
|
||||
|
||||
applyTouchMove(differenceX, differenceY);
|
||||
startOffset = currentOffset;
|
||||
|
||||
var currentTime = (new Date()).getTime();
|
||||
|
||||
var timeGap = currentTime - startTime;
|
||||
if (timeGap > 0) {
|
||||
speed.x = differenceX / timeGap;
|
||||
speed.y = differenceY / timeGap;
|
||||
startTime = currentTime;
|
||||
}
|
||||
|
||||
if (shouldPreventDefault(differenceX, differenceY)) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,6 +133,11 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!speed.x && !speed.y) {
|
||||
clearInterval(easingLoop);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
|
||||
clearInterval(easingLoop);
|
||||
return;
|
||||
@@ -143,9 +157,7 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
|
||||
i.event.bind(element, 'touchstart', touchStart);
|
||||
i.event.bind(element, 'touchmove', touchMove);
|
||||
i.event.bind(element, 'touchend', touchEnd);
|
||||
}
|
||||
|
||||
if (supportsIePointer) {
|
||||
} else if (supportsIePointer) {
|
||||
if (window.PointerEvent) {
|
||||
i.event.bind(window, 'pointerdown', globalTouchStart);
|
||||
i.event.bind(window, 'pointerup', globalTouchEnd);
|
||||
@@ -162,7 +174,11 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function (element, supportsTouch, supportsIePointer) {
|
||||
module.exports = function (element) {
|
||||
if (!_.env.supportsTouch && !_.env.supportsIePointer) {
|
||||
return;
|
||||
}
|
||||
|
||||
var i = instances.get(element);
|
||||
bindTouchHandler(element, i, supportsTouch, supportsIePointer);
|
||||
bindTouchHandler(element, i, _.env.supportsTouch, _.env.supportsIePointer);
|
||||
};
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
var cls = require('../lib/class')
|
||||
, h = require('../lib/helper')
|
||||
, instances = require('./instances')
|
||||
, updateGeometry = require('./update-geometry');
|
||||
var _ = require('../lib/helper');
|
||||
var cls = require('../lib/class');
|
||||
var instances = require('./instances');
|
||||
var updateGeometry = require('./update-geometry');
|
||||
var autoupdate = require('./autoupdate');
|
||||
var resizer = require('./resizer');
|
||||
|
||||
// Handlers
|
||||
var clickRailHandler = require('./handler/click-rail')
|
||||
, dragScrollbarHandler = require('./handler/drag-scrollbar')
|
||||
, keyboardHandler = require('./handler/keyboard')
|
||||
, mouseWheelHandler = require('./handler/mouse-wheel')
|
||||
, nativeScrollHandler = require('./handler/native-scroll')
|
||||
, selectionHandler = require('./handler/selection')
|
||||
, touchHandler = require('./handler/touch');
|
||||
var handlers = {
|
||||
'click-rail': require('./handler/click-rail'),
|
||||
'drag-scrollbar': require('./handler/drag-scrollbar'),
|
||||
'keyboard': require('./handler/keyboard'),
|
||||
'wheel': require('./handler/mouse-wheel'),
|
||||
'touch': require('./handler/touch'),
|
||||
'selection': require('./handler/selection')
|
||||
};
|
||||
var nativeScrollHandler = require('./handler/native-scroll');
|
||||
|
||||
module.exports = function (element, userSettings) {
|
||||
userSettings = typeof userSettings === 'object' ? userSettings : {};
|
||||
@@ -22,24 +26,19 @@ module.exports = function (element, userSettings) {
|
||||
// Create a plugin instance.
|
||||
var i = instances.add(element);
|
||||
|
||||
i.settings = h.extend(i.settings, userSettings);
|
||||
i.settings = _.extend(i.settings, userSettings);
|
||||
cls.add(element, 'ps-theme-' + i.settings.theme);
|
||||
|
||||
clickRailHandler(element);
|
||||
dragScrollbarHandler(element);
|
||||
mouseWheelHandler(element);
|
||||
i.settings.handlers.forEach(function (handlerName) {
|
||||
handlers[handlerName](element);
|
||||
});
|
||||
|
||||
nativeScrollHandler(element);
|
||||
|
||||
if (i.settings.useSelectionScroll) {
|
||||
selectionHandler(element);
|
||||
}
|
||||
|
||||
if (h.env.supportsTouch || h.env.supportsIePointer) {
|
||||
touchHandler(element, h.env.supportsTouch, h.env.supportsIePointer);
|
||||
}
|
||||
if (i.settings.useKeyboard) {
|
||||
keyboardHandler(element);
|
||||
}
|
||||
|
||||
updateGeometry(element);
|
||||
|
||||
if (i.settings.autoupdate) {
|
||||
autoupdate(element);
|
||||
resizer(element);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
var cls = require('../lib/class')
|
||||
, d = require('../lib/dom')
|
||||
, defaultSettings = require('./default-setting')
|
||||
, EventManager = require('../lib/event-manager')
|
||||
, guid = require('../lib/guid')
|
||||
, h = require('../lib/helper');
|
||||
var _ = require('../lib/helper');
|
||||
var cls = require('../lib/class');
|
||||
var defaultSettings = require('./default-setting');
|
||||
var dom = require('../lib/dom');
|
||||
var EventManager = require('../lib/event-manager');
|
||||
var guid = require('../lib/guid');
|
||||
|
||||
var instances = {};
|
||||
|
||||
function Instance(element) {
|
||||
var i = this;
|
||||
|
||||
i.settings = h.clone(defaultSettings);
|
||||
i.settings = _.clone(defaultSettings);
|
||||
i.containerWidth = null;
|
||||
i.containerHeight = null;
|
||||
i.contentWidth = null;
|
||||
i.contentHeight = null;
|
||||
|
||||
i.isRtl = d.css(element, 'direction') === "rtl";
|
||||
i.isRtl = dom.css(element, 'direction') === "rtl";
|
||||
i.isNegativeScroll = (function () {
|
||||
var originalScrollLeft = element.scrollLeft;
|
||||
var result = null;
|
||||
@@ -39,67 +39,55 @@ function Instance(element) {
|
||||
cls.remove(element, 'ps-focus');
|
||||
}
|
||||
|
||||
i.scrollbarXRail = d.appendTo(d.e('div', 'ps-scrollbar-x-rail'), element);
|
||||
i.scrollbarX = d.appendTo(d.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
|
||||
i.scrollbarXRail = dom.appendTo(dom.e('div', 'ps-scrollbar-x-rail'), element);
|
||||
i.scrollbarX = dom.appendTo(dom.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
|
||||
i.scrollbarX.setAttribute('tabindex', 0);
|
||||
i.event.bind(i.scrollbarX, 'focus', focus);
|
||||
i.event.bind(i.scrollbarX, 'blur', blur);
|
||||
i.scrollbarXActive = null;
|
||||
i.scrollbarXWidth = null;
|
||||
i.scrollbarXLeft = null;
|
||||
i.scrollbarXBottom = h.toInt(d.css(i.scrollbarXRail, 'bottom'));
|
||||
i.scrollbarXBottom = _.toInt(dom.css(i.scrollbarXRail, 'bottom'));
|
||||
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'));
|
||||
i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : _.toInt(dom.css(i.scrollbarXRail, 'top'));
|
||||
i.railBorderXWidth = _.toInt(dom.css(i.scrollbarXRail, 'borderLeftWidth')) + _.toInt(dom.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', '');
|
||||
dom.css(i.scrollbarXRail, 'display', 'block');
|
||||
i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight'));
|
||||
dom.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);
|
||||
i.scrollbarYRail = dom.appendTo(dom.e('div', 'ps-scrollbar-y-rail'), element);
|
||||
i.scrollbarY = dom.appendTo(dom.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
|
||||
i.scrollbarY.setAttribute('tabindex', 0);
|
||||
i.event.bind(i.scrollbarY, 'focus', focus);
|
||||
i.event.bind(i.scrollbarY, 'blur', blur);
|
||||
i.scrollbarYActive = null;
|
||||
i.scrollbarYHeight = null;
|
||||
i.scrollbarYTop = null;
|
||||
i.scrollbarYRight = h.toInt(d.css(i.scrollbarYRail, 'right'));
|
||||
i.scrollbarYRight = _.toInt(dom.css(i.scrollbarYRail, 'right'));
|
||||
i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN
|
||||
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.scrollbarYLeft = i.isScrollbarYUsingRight ? null : _.toInt(dom.css(i.scrollbarYRail, 'left'));
|
||||
i.scrollbarYOuterWidth = i.isRtl ? _.outerWidth(i.scrollbarY) : null;
|
||||
i.railBorderYWidth = _.toInt(dom.css(i.scrollbarYRail, 'borderTopWidth')) + _.toInt(dom.css(i.scrollbarYRail, 'borderBottomWidth'));
|
||||
dom.css(i.scrollbarYRail, 'display', 'block');
|
||||
i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom'));
|
||||
dom.css(i.scrollbarYRail, 'display', '');
|
||||
i.railYHeight = null;
|
||||
i.railYRatio = null;
|
||||
}
|
||||
|
||||
function getId(element) {
|
||||
if (typeof element.dataset === 'undefined') {
|
||||
return element.getAttribute('data-ps-id');
|
||||
} else {
|
||||
return element.dataset.psId;
|
||||
}
|
||||
return element.getAttribute('data-ps-id');
|
||||
}
|
||||
|
||||
function setId(element, id) {
|
||||
if (typeof element.dataset === 'undefined') {
|
||||
element.setAttribute('data-ps-id', id);
|
||||
} else {
|
||||
element.dataset.psId = id;
|
||||
}
|
||||
element.setAttribute('data-ps-id', id);
|
||||
}
|
||||
|
||||
function removeId(element) {
|
||||
if (typeof element.dataset === 'undefined') {
|
||||
element.removeAttribute('data-ps-id');
|
||||
} else {
|
||||
delete element.dataset.psId;
|
||||
}
|
||||
element.removeAttribute('data-ps-id');
|
||||
}
|
||||
|
||||
exports.add = function (element) {
|
||||
|
||||
15
src/js/plugin/resizer.js
Normal file
15
src/js/plugin/resizer.js
Normal file
@@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
var update = require('./update');
|
||||
var instances = require('./instances');
|
||||
var _ = require('../lib/helper');
|
||||
|
||||
module.exports = function (element) {
|
||||
var i = instances.get(element);
|
||||
|
||||
var onResize = function () {
|
||||
update(element);
|
||||
};
|
||||
|
||||
i.event.bind(window, 'resize', _.debounce(onResize, 60));
|
||||
};
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
var cls = require('../lib/class')
|
||||
, d = require('../lib/dom')
|
||||
, h = require('../lib/helper')
|
||||
, instances = require('./instances')
|
||||
, updateScroll = require('./update-scroll');
|
||||
var _ = require('../lib/helper');
|
||||
var cls = require('../lib/class');
|
||||
var dom = require('../lib/dom');
|
||||
var instances = require('./instances');
|
||||
var updateScroll = require('./update-scroll');
|
||||
|
||||
function getThumbSize(i, thumbSize) {
|
||||
if (i.settings.minScrollbarLength) {
|
||||
@@ -28,7 +28,7 @@ function updateCss(element, i) {
|
||||
} else {
|
||||
xRailOffset.top = i.scrollbarXTop + element.scrollTop;
|
||||
}
|
||||
d.css(i.scrollbarXRail, xRailOffset);
|
||||
dom.css(i.scrollbarXRail, xRailOffset);
|
||||
|
||||
var yRailOffset = {top: element.scrollTop, height: i.railYHeight};
|
||||
if (i.isScrollbarYUsingRight) {
|
||||
@@ -44,10 +44,10 @@ function updateCss(element, i) {
|
||||
yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
|
||||
}
|
||||
}
|
||||
d.css(i.scrollbarYRail, yRailOffset);
|
||||
dom.css(i.scrollbarYRail, yRailOffset);
|
||||
|
||||
d.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth});
|
||||
d.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth});
|
||||
dom.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth});
|
||||
dom.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth});
|
||||
}
|
||||
|
||||
module.exports = function (element) {
|
||||
@@ -60,30 +60,30 @@ module.exports = function (element) {
|
||||
|
||||
var existingRails;
|
||||
if (!element.contains(i.scrollbarXRail)) {
|
||||
existingRails = d.queryChildren(element, '.ps-scrollbar-x-rail');
|
||||
existingRails = dom.queryChildren(element, '.ps-scrollbar-x-rail');
|
||||
if (existingRails.length > 0) {
|
||||
existingRails.forEach(function (rail) {
|
||||
d.remove(rail);
|
||||
dom.remove(rail);
|
||||
});
|
||||
}
|
||||
d.appendTo(i.scrollbarXRail, element);
|
||||
dom.appendTo(i.scrollbarXRail, element);
|
||||
}
|
||||
if (!element.contains(i.scrollbarYRail)) {
|
||||
existingRails = d.queryChildren(element, '.ps-scrollbar-y-rail');
|
||||
existingRails = dom.queryChildren(element, '.ps-scrollbar-y-rail');
|
||||
if (existingRails.length > 0) {
|
||||
existingRails.forEach(function (rail) {
|
||||
d.remove(rail);
|
||||
dom.remove(rail);
|
||||
});
|
||||
}
|
||||
d.appendTo(i.scrollbarYRail, element);
|
||||
dom.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((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
|
||||
i.scrollbarXWidth = getThumbSize(i, _.toInt(i.railXWidth * i.containerWidth / i.contentWidth));
|
||||
i.scrollbarXLeft = _.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
|
||||
} else {
|
||||
i.scrollbarXActive = false;
|
||||
}
|
||||
@@ -92,8 +92,8 @@ module.exports = function (element) {
|
||||
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));
|
||||
i.scrollbarYHeight = getThumbSize(i, _.toInt(i.railYHeight * i.containerHeight / i.contentHeight));
|
||||
i.scrollbarYTop = _.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight));
|
||||
} else {
|
||||
i.scrollbarYActive = false;
|
||||
}
|
||||
|
||||
@@ -2,29 +2,14 @@
|
||||
|
||||
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;
|
||||
var lastTop;
|
||||
var lastLeft;
|
||||
|
||||
upEvent.initEvent('ps-scroll-up', true, true);
|
||||
downEvent.initEvent('ps-scroll-down', true, true);
|
||||
leftEvent.initEvent('ps-scroll-left', true, true);
|
||||
rightEvent.initEvent('ps-scroll-right', true, true);
|
||||
yEvent.initEvent('ps-scroll-y', true, true);
|
||||
xEvent.initEvent('ps-scroll-x', true, true);
|
||||
xStartEvent.initEvent('ps-x-reach-start', true, true);
|
||||
xEndEvent.initEvent('ps-x-reach-end', true, true);
|
||||
yStartEvent.initEvent('ps-y-reach-start', true, true);
|
||||
yEndEvent.initEvent('ps-y-reach-end', true, true);
|
||||
var createDOMEvent = function (name) {
|
||||
var event = document.createEvent("Event");
|
||||
event.initEvent(name, true, true);
|
||||
return event;
|
||||
};
|
||||
|
||||
module.exports = function (element, axis, value) {
|
||||
if (typeof element === 'undefined') {
|
||||
@@ -41,24 +26,38 @@ module.exports = function (element, axis, value) {
|
||||
|
||||
if (axis === 'top' && value <= 0) {
|
||||
element.scrollTop = value = 0; // don't allow negative scroll
|
||||
element.dispatchEvent(yStartEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-y-reach-start'));
|
||||
}
|
||||
|
||||
if (axis === 'left' && value <= 0) {
|
||||
element.scrollLeft = value = 0; // don't allow negative scroll
|
||||
element.dispatchEvent(xStartEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-x-reach-start'));
|
||||
}
|
||||
|
||||
var i = instances.get(element);
|
||||
|
||||
if (axis === 'top' && value >= i.contentHeight - i.containerHeight) {
|
||||
element.scrollTop = value = i.contentHeight - i.containerHeight; // don't allow scroll past container
|
||||
element.dispatchEvent(yEndEvent);
|
||||
// don't allow scroll past container
|
||||
value = i.contentHeight - i.containerHeight;
|
||||
if (value - element.scrollTop <= 1) {
|
||||
// mitigates rounding errors on non-subpixel scroll values
|
||||
value = element.scrollTop;
|
||||
} else {
|
||||
element.scrollTop = value;
|
||||
}
|
||||
element.dispatchEvent(createDOMEvent('ps-y-reach-end'));
|
||||
}
|
||||
|
||||
if (axis === 'left' && value >= i.contentWidth - i.containerWidth) {
|
||||
element.scrollLeft = value = i.contentWidth - i.containerWidth; // don't allow scroll past container
|
||||
element.dispatchEvent(xEndEvent);
|
||||
// don't allow scroll past container
|
||||
value = i.contentWidth - i.containerWidth;
|
||||
if (value - element.scrollLeft <= 1) {
|
||||
// mitigates rounding errors on non-subpixel scroll values
|
||||
value = element.scrollLeft;
|
||||
} else {
|
||||
element.scrollLeft = value;
|
||||
}
|
||||
element.dispatchEvent(createDOMEvent('ps-x-reach-end'));
|
||||
}
|
||||
|
||||
if (!lastTop) {
|
||||
@@ -70,29 +69,29 @@ module.exports = function (element, axis, value) {
|
||||
}
|
||||
|
||||
if (axis === 'top' && value < lastTop) {
|
||||
element.dispatchEvent(upEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-up'));
|
||||
}
|
||||
|
||||
if (axis === 'top' && value > lastTop) {
|
||||
element.dispatchEvent(downEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-down'));
|
||||
}
|
||||
|
||||
if (axis === 'left' && value < lastLeft) {
|
||||
element.dispatchEvent(leftEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-left'));
|
||||
}
|
||||
|
||||
if (axis === 'left' && value > lastLeft) {
|
||||
element.dispatchEvent(rightEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-right'));
|
||||
}
|
||||
|
||||
if (axis === 'top') {
|
||||
element.scrollTop = lastTop = value;
|
||||
element.dispatchEvent(yEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-y'));
|
||||
}
|
||||
|
||||
if (axis === 'left') {
|
||||
element.scrollLeft = lastLeft = value;
|
||||
element.dispatchEvent(xEvent);
|
||||
element.dispatchEvent(createDOMEvent('ps-scroll-x'));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
var d = require('../lib/dom')
|
||||
, h = require('../lib/helper')
|
||||
, instances = require('./instances')
|
||||
, updateGeometry = require('./update-geometry')
|
||||
, updateScroll = require('./update-scroll');
|
||||
var _ = require('../lib/helper');
|
||||
var dom = require('../lib/dom');
|
||||
var instances = require('./instances');
|
||||
var updateGeometry = require('./update-geometry');
|
||||
var updateScroll = require('./update-scroll');
|
||||
|
||||
module.exports = function (element) {
|
||||
var i = instances.get(element);
|
||||
@@ -17,14 +17,14 @@ module.exports = function (element) {
|
||||
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'));
|
||||
dom.css(i.scrollbarXRail, 'display', 'block');
|
||||
dom.css(i.scrollbarYRail, 'display', 'block');
|
||||
i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight'));
|
||||
i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom'));
|
||||
|
||||
// Hide scrollbars not to affect scrollWidth and scrollHeight
|
||||
d.css(i.scrollbarXRail, 'display', 'none');
|
||||
d.css(i.scrollbarYRail, 'display', 'none');
|
||||
dom.css(i.scrollbarXRail, 'display', 'none');
|
||||
dom.css(i.scrollbarYRail, 'display', 'none');
|
||||
|
||||
updateGeometry(element);
|
||||
|
||||
@@ -32,6 +32,6 @@ module.exports = function (element) {
|
||||
updateScroll(element, 'top', element.scrollTop);
|
||||
updateScroll(element, 'left', element.scrollLeft);
|
||||
|
||||
d.css(i.scrollbarXRail, 'display', '');
|
||||
d.css(i.scrollbarYRail, 'display', '');
|
||||
dom.css(i.scrollbarXRail, 'display', '');
|
||||
dom.css(i.scrollbarYRail, 'display', '');
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user