Compare commits

...

41 Commits
0.5.4 ... 0.5.9

Author SHA1 Message Date
Hyunje Alex Jun
254b22877c Release 0.5.9
1. Change how `in-scrolling` works.
2. Bug fixes.

This is the last release of an old-styled version. In the next version,
it may change a lot. Please stay tuned!
2015-02-11 15:43:34 +00:00
Hyunje Alex Jun
1a6197cbed Add a table example. 2015-02-05 20:06:05 +00:00
Hyunje Alex Jun
2fc41e7045 Add a guard to check if activeElement exists. 2015-02-05 19:18:35 +00:00
Hyunje Alex Jun
bd22fc0e58 2014 -> 2015.
Happy new year!
2015-01-08 17:36:54 +00:00
Hyunje Alex Jun
3b3431e226 Merge pull request #270 from DanielApt/SCSS_Colors
Define the used colors as variables
2014-12-17 00:22:25 +09:00
DanielApt
373838d825 Define the used colors as variables 2014-12-16 13:21:16 +00:00
Hyunje Alex Jun
b927c177ca Change how .in-scrolling works.
Now we add `.ps-in-scrolling` class in a container div.
`pointer-events: none;` is also added for the class.
2014-12-09 23:57:52 +00:00
Hyunje Alex Jun
d6558c492d Merge pull request #259 from smithl/patch-1
Update README.md
2014-12-02 18:27:10 +00:00
Smith
e1db204dd4 Update README.md
Your english isn't bad at all - great work on the plugin! Here are a few text updates to the readme.
2014-12-02 09:47:34 -08:00
Hyunje Alex Jun
dcdefebded Release 0.5.8
1. Improve mouse handler logic.
2. Add rail margin detection.
3. Add swipePropagation option.
4. Bug fixes.
2014-12-02 11:40:46 +00:00
Hyunje Alex Jun
fae5c001d4 Update README.md
Add `swipePropagation`.
2014-12-02 11:38:54 +00:00
Hyunje Alex Jun
febcaa3603 Add an example for scrollbar margin. 2014-12-02 11:34:45 +00:00
Hyunje Alex Jun
20576ac717 Merge pull request #252 from tkhyn/master
Detects margins around the rails
2014-12-02 11:34:07 +00:00
Hyunje Alex Jun
7ce708216d Small style fixes for preventDefault functions. 2014-12-02 11:24:36 +00:00
DI-john
931be25635 propagate mobile swipe gestures to page where appropriate 2014-12-02 11:00:37 +00:00
Thomas Khyn
74d0fcb1de Detects margins around the rails 2014-11-17 14:18:37 +13:00
Hyunje Alex Jun
9b3301fd0c Merge pull request #251 from tatarinov/master
Renamed 'int' helper in 'getInt' #250
2014-11-14 12:27:05 +00:00
tatarinov
a94df46fe3 Removed unnecessary semicolon 2014-11-14 10:25:19 +04:00
tatarinov
20053e9cf1 Renamed 'int' helper in 'getInt' #250 2014-11-14 10:04:07 +04:00
Hyunje Alex Jun
aaab294dc4 Add an example for always-visible scrollbars. 2014-11-11 14:40:03 +00:00
Hyunje Alex Jun
e9fcc0f02a Temporary fix for mousewheel problem of select in FF and IE.
Resolve #247.
2014-11-11 13:29:09 +00:00
Alexandr Subbotin
05b20f45ef decrease mouse handlers count and every-time class checking during mousemove 2014-11-11 13:28:58 +00:00
Hyunje Alex Jun
3821413589 Release 0.5.7.
1. IE mouse pointer event bug fix.
2. Use scss for stylesheet.
3. Clear intervals when destroyed.
4. Bug fixes.
2014-11-05 19:02:45 +00:00
Hyunje Alex Jun
08a387d9c1 Add removable-list-element example. 2014-11-05 19:02:00 +00:00
Hyunje Alex Jun
1849e64122 Remove remaining inline display style.
It caused regression bugs.
2014-11-05 18:51:52 +00:00
Hyunje Alex Jun
f9c3dc0b20 Change name of variable breakingProcess.
It's too ambiguous to understand the purpose of the variable.
2014-10-31 19:25:43 +00:00
Hyunje Alex Jun
aa92487ed3 Clear intervals if the plugin is destroyed. 2014-10-31 19:25:13 +00:00
Hyunje Alex Jun
a3bf38ada2 Update README.md
Add FAQ.
2014-10-31 19:16:36 +00:00
Hyunje Alex Jun
d24f9bd41b Use scss for stylesheet.
We can build the scss source to .css and .min.css files with the
`grunt build` command.
2014-10-31 02:20:22 +00:00
Hyunje Alex Jun
5be50316ca Merge pull request #239 from darthmaim/bugfix_ie10_pointertype
Don't handle mouse pointer events as touch in IE10.
2014-10-30 18:21:43 +00:00
Konrad Liebig
94be67d998 Don't handle mouse pointer events as touch in IE10 2014-10-30 17:04:20 +01:00
Hyunje Alex Jun
17fd46a07d Release 0.5.6.
1. Add scrolling with selection.
2. Bug fixes.
2014-10-28 18:02:22 +00:00
Hyunje Alex Jun
f099448e44 Change how scrollbar rails are being hidden.
Inline CSS change is bad practice.
2014-10-28 18:01:23 +00:00
Hyunje Alex Jun
d0b97e4039 Add selection handler.
Now perfect-scrollbar supports scrolling by selection.
2014-10-28 17:49:16 +00:00
Hyunje Alex Jun
f2342f2678 Change the way to handle event class name.
Use factory pattern to handle it, instead of using + operator of
string.
2014-10-28 16:41:36 +00:00
Hyunje Alex Jun
967c30a5e4 Shouldn't prevent default for touchStart.
Default touch event shouldn't be prevented.
2014-10-28 14:33:07 +00:00
Hyunje Alex Jun
7cf8303b30 Release 0.5.5.
1. Bug fixes.
2014-10-24 12:06:04 +01:00
Hyunje Alex Jun
7dd6335965 Filter touch events not to be handled.
In IE 10/11, MSPointer event is fired by mouse. It shouldn't be handled.

Also, Exception has occurred with event.targetTouches, and this commit
fixed it too.
2014-10-24 12:03:55 +01:00
Hyunje Alex Jun
494d68fe02 Merge pull request #231 from suxxes/patch-1
Correction for railBorderYWidth calculation
2014-10-22 16:10:07 +01:00
Fedor
3dde3ebb0c Correction for railBorderYWidth calculation 2014-10-22 17:09:45 +04:00
Hyunje Alex Jun
12086573fc Update README.md
Add `npm` to install section.
2014-10-21 21:43:07 +01:00
14 changed files with 806 additions and 282 deletions

View File

@@ -1,6 +1,7 @@
'use strict';
module.exports = function (grunt) {
require('load-grunt-tasks')(grunt);
// Project configuration.
grunt.initConfig({
@@ -38,15 +39,6 @@ module.exports = function (grunt) {
src: 'src/perfect-scrollbar.js'
}
},
csslint: {
strict: {
options: {
csslintrc: '.csslintrc',
'import': 2
},
src: ['src/perfect-scrollbar.css']
}
},
cssmin: {
options: {
banner: '<%= banner %>'
@@ -67,17 +59,16 @@ module.exports = function (grunt) {
createTag: false,
push: false
}
},
sass: {
dist: {
files: {
'src/perfect-scrollbar.css': 'src/perfect-scrollbar.scss'
}
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-csslint');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-bump');
grunt.registerTask('default', 'List commands', function () {
grunt.log.writeln("");
@@ -85,12 +76,11 @@ module.exports = function (grunt) {
grunt.log.writeln("Run 'grunt build' to minify the source files");
});
grunt.registerTask('lint', ['jshint', 'csslint']);
grunt.registerTask('build', ['clean', 'uglify', 'cssmin']);
grunt.registerTask('lint', ['jshint']);
grunt.registerTask('build', ['clean', 'uglify', 'sass', 'cssmin']);
grunt.registerTask('travis', ['lint']);
grunt.registerTask('release', 'Release a new version', function (arg) {
var bumpType = arg ? ':' + arg : '';
grunt.task.run(['lint', 'bump' + bumpType, 'build']);
});
};

View File

@@ -8,8 +8,8 @@ Why perfect-scrollbar?
I worked on a personal project recently, and I was trying to find the jQuery scrollbar plugin that's *perfect*. But there was no *perfect* scrollbar plugin. That's why I decided to make one.
perfect-scrollbar is very tiny but *perfect* (for me, and maybe for the most of developers) jQuery scrollbar plugin.
I hope you love this!
perfect-scrollbar is very tiny but *perfect* (for me, and maybe for most developers) jQuery scrollbar plugin.
I hope you love it!
Demo: http://noraesae.github.com/perfect-scrollbar/
@@ -31,27 +31,33 @@ Yes! the only thing that's not *perfect* is my English.
* perfect-scrollbar has some requirements, but doesn't change or add any style on original elements.
* perfect-scrollbar is designed not to have width or height. It's fixed on the right and bottom side of the container.
* You can change nearly all css styles of the scrollbar. The scrollbar design has no dependency on scripts.
* perfect-scrollbar support 'update' function. Whenever you need to update the size or position of the scrollbar, just update.
* Additionally, perfect-scrollbar do use 'scrollTop' and 'scrollLeft', not absolute position or something messy.
* perfect-scrollbar supports an 'update' function. Whenever you need to update the size or position of the scrollbar, just update.
* Additionally, perfect-scrollbar uses 'scrollTop' and 'scrollLeft', not absolute positioning or something messy.
It's cool, isn't it?
Install
-------
You can download the latest stable version with download links in [Github Page](http://noraesae.github.io/perfect-scrollbar/). You also can find all releases in [Releases](https://github.com/noraesae/perfect-scrollbar/releases) page.
You can download the latest stable version with download links at [Github Page](http://noraesae.github.io/perfect-scrollbar/). You also can find all releases at [Releases](https://github.com/noraesae/perfect-scrollbar/releases) page.
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 can be fixed.
```
git clone https://github.com/noraesae/perfect-scrollbar.git
cd perfect-scrollbar/src
$ git clone https://github.com/noraesae/perfect-scrollbar.git
$ cd perfect-scrollbar/src
```
You can use [Bower](http://bower.io/) to install the plugin. The plugin is registered as `perfect-scrollbar`.
```
bower install perfect-scrollbar
$ bower install perfect-scrollbar
```
It's registered on [npm](https://www.npmjs.org/package/perfect-scrollbar) as `perfect-scrollbar`.
```
$ npm install perfect-scrollbar
```
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).
@@ -59,16 +65,16 @@ You can also load it from [cdnjs](http://cdnjs.com/). It is registered as [`jque
Requirements
------------
To make this plugin *perfect*, some requirements were not avoidable. But they're all very trivial and there's nothing to worry about.
To make this plugin *perfect*, some requirements were unavoidable. But, they're all very trivial and there is nothing to worry about.
* the container must have a 'position' 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.
The requirement below is for perfect-scrollbar &lt;= 0.3.4
The below requirement is for perfect-scrollbar &lt;= 0.3.4
* there must be the *one* content element(like div) for the container.
* there must be the *one* content element (like div) for the container.
Optional parameters
-------------------
@@ -80,10 +86,12 @@ The scroll speed applied to mousewheel event.
**Default: 1**
### wheelPropagation
If this option is true, when the scroll reach the end of the side, mousewheel event will be propagated to parent element.
*Currently not supported for touch events*
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**
### minScrollbarLength
When set to an integer value, the thumb part of the scrollbar will not shrink below that number of pixels.
@@ -167,12 +175,12 @@ $("#Demo").scrollTop(0);
$("#Demo").perfectScrollbar('update');
```
Also you can get the informations about how to use the plugin from example codes in the `examples` directory of the source tree.
Also you can get information about how to use the plugin from code in the `examples` directory of the source tree.
Contribution
------------
#### Please read [Contributing](https://github.com/noraesae/perfect-scrollbar/wiki/Contributing) in the wiki before making any contibution.
#### Please read [Contributing](https://github.com/noraesae/perfect-scrollbar/wiki/Contributing) in the wiki before making any contribution.
I *really* welcome contributions! Please feel free to fork and issue pull requests when...
@@ -186,7 +194,7 @@ For IE problems, please refer to [IE Support](https://github.com/noraesae/perfec
IE Support
----------
The plugin would work in IEs >= IE9(not well, though).
The plugin would work in IEs >= IE9 (not well, though).
**The patches to fix problems in IE<=8 won't be accepted.**
@@ -197,10 +205,12 @@ Helpdesk
If you have any idea to improve this project or any problem using this, please feel free to upload an [issue](https://github.com/noraesae/perfect-scrollbar/issues).
For common problems there is a [FAQ](https://github.com/noraesae/perfect-scrollbar/wiki/FAQ) wiki page. Please check the page before uploading an issue.
License
-------
The MIT License (MIT) Copyright (c) 2012, 2014 Hyunje Alex Jun and other contributors.
The MIT License (MIT) Copyright (c) 2015 Hyunje Alex Jun and other contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@@ -1,6 +1,6 @@
{
"name": "perfect-scrollbar",
"version": "0.5.4",
"version": "0.5.9",
"homepage": "http://noraesae.github.io/perfect-scrollbar/",
"authors": [
"Hyunje Alex Jun <me@noraesae.net>"

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>perfect-scrollbar example</title>
<link href="../src/perfect-scrollbar.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../src/perfect-scrollbar.js"></script>
<style>
h1 { text-align: center; }
.container { position:relative; margin:0px auto; padding:0px; width: 600px; height: 400px; overflow: hidden; }
.container .content { background-image: url('./azusa.jpg'); width: 1280px; height: 720px; }
</style>
<style>
/* to make scrollbars always visible */
.always-visible.ps-container > .ps-scrollbar-x-rail,
.always-visible.ps-container > .ps-scrollbar-y-rail {
opacity: 0.6;
}
</style>
<script>
jQuery(document).ready(function ($) {
"use strict";
$('.container').perfectScrollbar();
});
</script>
</head>
<body>
<h1>Default</h1>
<div class="container">
<div class="content">
</div>
</div>
<h1>Always visible</h1>
<div class="container always-visible">
<div class="content">
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>perfect-scrollbar example</title>
<link href="../src/perfect-scrollbar.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../src/perfect-scrollbar.js"></script>
<style>
#test {
border: 1px solid gray;
max-height: 300px;
width: 400px;
overflow: hidden;
position: relative;
}
#test .element {
margin: 1px;
background-color: #cec;
height: 44px;
line-height: 44px;
}
</style>
<script type="text/javascript">
$(document).ready(function ($) {
var test = $('#test');
test.perfectScrollbar();
test.find('a').click(function () {
$(this).parent().remove();
test.perfectScrollbar('update');
});
});
</script>
</head>
<body>
<div id="test" class="wrapper">
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
<div class='element'>Hello! Click <a href='#'>here</a> to remove this!</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>perfect-scrollbar example</title>
<link href="../src/perfect-scrollbar.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../src/perfect-scrollbar.js"></script>
<style>
.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; }
.spacer { text-align:center }
.ps-scrollbar-x-rail {
margin: 0 3px;
}
.ps-scrollbar-y-rail {
margin: 3px 0;
}
</style>
<script>
jQuery(document).ready(function ($) {
"use strict";
$('#Default').perfectScrollbar();
});
</script>
</head>
<body>
<div id="Default" class="contentHolder">
<div class="content">
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,83 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>perfect-scrollbar example</title>
<link href="../src/perfect-scrollbar.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../src/perfect-scrollbar.js"></script>
<style>
#table {
font-size: 20px;
}
#table thead, #table tbody, #table tr {
display: block;
width: 600px;
border-spacing: 0;
border-collapse: collapse;
}
#table tbody {
height: 100px;
overflow-y: hidden;
position: relative;
}
#table tbody td, #table thead th {
display: block;
border: 1px solid black;
width: 200px;
float: left;
box-sizing: border-box;
}
</style>
<script type="text/javascript">
$(document).ready(function ($) {
$('#table tbody').perfectScrollbar();
});
</script>
</head>
<body>
<div id="table" class="wrapper">
<table id='table'>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Occupation</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alex</td>
<td>20</td>
<td>Student</td>
</tr>
<tr>
<td>Paul</td>
<td>23</td>
<td>Engineer</td>
</tr>
<tr>
<td>Chris</td>
<td>19</td>
<td>Human being</td>
</tr>
<tr>
<td>Alex</td>
<td>20</td>
<td>Student</td>
</tr>
<tr>
<td>Paul</td>
<td>23</td>
<td>Engineer</td>
</tr>
<tr>
<td>Chris</td>
<td>19</td>
<td>Human being</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@@ -1,5 +1,5 @@
/*! perfect-scrollbar - v0.5.4
/*! perfect-scrollbar - v0.5.9
* http://noraesae.github.com/perfect-scrollbar/
* Copyright (c) 2014 Hyunje Alex Jun; Licensed MIT */
* Copyright (c) 2015 Hyunje Alex Jun; Licensed MIT */
.ps-container>.ps-scrollbar-x-rail{position:absolute;bottom:3px;height:8px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;opacity:0;filter:alpha(opacity=0);-o-transition:background-color .2s linear,opacity .2s linear;-webkit-transition:background-color .2s linear,opacity .2s linear;-moz-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear}.ps-container:hover>.ps-scrollbar-x-rail{opacity:.6;filter:alpha(opacity=60)}.ps-container>.ps-scrollbar-x-rail:hover{background-color:#eee;opacity:.9;filter:alpha(opacity=90)}.ps-container>.ps-scrollbar-x-rail.in-scrolling{background-color:#eee;opacity:.9;filter:alpha(opacity=90)}.ps-container>.ps-scrollbar-y-rail{position:absolute;right:3px;width:8px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;opacity:0;filter:alpha(opacity=0);-o-transition:background-color .2s linear,opacity .2s linear;-webkit-transition:background-color .2s linear,opacity .2s linear;-moz-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear}.ps-container:hover>.ps-scrollbar-y-rail{opacity:.6;filter:alpha(opacity=60)}.ps-container>.ps-scrollbar-y-rail:hover{background-color:#eee;opacity:.9;filter:alpha(opacity=90)}.ps-container>.ps-scrollbar-y-rail.in-scrolling{background-color:#eee;opacity:.9;filter:alpha(opacity=90)}.ps-container>.ps-scrollbar-x-rail>.ps-scrollbar-x{position:absolute;bottom:0;height:8px;background-color:#aaa;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-o-transition:background-color .2s linear;-webkit-transition:background-color.2s linear;-moz-transition:background-color .2s linear;transition:background-color .2s linear}.ps-container>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x{background-color:#999}.ps-container>.ps-scrollbar-y-rail>.ps-scrollbar-y{position:absolute;right:0;width:8px;background-color:#aaa;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-o-transition:background-color .2s linear;-webkit-transition:background-color.2s linear;-moz-transition:background-color .2s linear;transition:background-color .2s linear}.ps-container>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y{background-color:#999}
.ps-container.ps-active-x>.ps-scrollbar-x-rail,.ps-container.ps-active-y>.ps-scrollbar-y-rail{display:block}.ps-container.ps-in-scrolling{pointer-events:none}.ps-container.ps-in-scrolling>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9;-ms-filter:"alpha(Opacity=90)";filter:alpha(opacity=90)}.ps-container.ps-in-scrolling>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999}.ps-container.ps-in-scrolling>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9;-ms-filter:"alpha(Opacity=90)";filter:alpha(opacity=90)}.ps-container.ps-in-scrolling>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999}.ps-container>.ps-scrollbar-x-rail{display:none;position:absolute;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;border-radius:4px;opacity:0;-ms-filter:"alpha(Opacity=0)";filter:alpha(opacity=0);-webkit-transition:background-color .2s linear,opacity .2s linear;-moz-transition:background-color .2s linear,opacity .2s linear;-o-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear;bottom:3px;height:8px}.ps-container>.ps-scrollbar-x-rail>.ps-scrollbar-x{position:absolute;background-color:#aaa;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;border-radius:4px;-webkit-transition:background-color .2s linear;-moz-transition:background-color .2s linear;-o-transition:background-color .2s linear;transition:background-color .2s linear;bottom:0;height:8px}.ps-container>.ps-scrollbar-y-rail{display:none;position:absolute;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;border-radius:4px;opacity:0;-ms-filter:"alpha(Opacity=0)";filter:alpha(opacity=0);-webkit-transition:background-color .2s linear,opacity .2s linear;-moz-transition:background-color .2s linear,opacity .2s linear;-o-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear;right:3px;width:8px}.ps-container>.ps-scrollbar-y-rail>.ps-scrollbar-y{position:absolute;background-color:#aaa;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;border-radius:4px;-webkit-transition:background-color .2s linear;-moz-transition:background-color .2s linear;-o-transition:background-color .2s linear;transition:background-color .2s linear;right:0;width:8px}.ps-container:hover.ps-in-scrolling{pointer-events:none}.ps-container:hover.ps-in-scrolling>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9;-ms-filter:"alpha(Opacity=90)";filter:alpha(opacity=90)}.ps-container:hover.ps-in-scrolling>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999}.ps-container:hover.ps-in-scrolling>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9;-ms-filter:"alpha(Opacity=90)";filter:alpha(opacity=90)}.ps-container:hover.ps-in-scrolling>.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:.6;-ms-filter:"alpha(Opacity=60)";filter:alpha(opacity=60)}.ps-container:hover>.ps-scrollbar-x-rail:hover{background-color:#eee;opacity:.9;-ms-filter:"alpha(Opacity=90)";filter:alpha(opacity=90)}.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:.9;-ms-filter:"alpha(Opacity=90)";filter:alpha(opacity=90)}.ps-container:hover>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y{background-color:#999}

File diff suppressed because one or more lines are too long

View File

@@ -1,12 +1,14 @@
{
"name": "perfect-scrollbar",
"version": "0.5.4",
"version": "0.5.9",
"description": "Tiny but perfect jquery scrollbar plugin.",
"author": "Hyunje Alex Jun <me@noraesae.net>",
"contributors": [{
"name": "Hyunje Alex Jun",
"email": "me@noraesae.net"
}],
"contributors": [
{
"name": "Hyunje Alex Jun",
"email": "me@noraesae.net"
}
],
"main": "src/perfect-scrollbar.js",
"repository": {
"type": "git",
@@ -30,7 +32,9 @@
"grunt-contrib-csslint": "~0.1.2",
"grunt-contrib-cssmin": "~0.6.1",
"grunt-contrib-jshint": "~0.1.1",
"grunt-contrib-uglify": "~0.1.1"
"grunt-contrib-uglify": "~0.1.1",
"grunt-sass": "^0.16.1",
"load-grunt-tasks": "^1.0.0"
},
"scripts": {
"test": "grunt travis --verbose"

View File

@@ -2,7 +2,7 @@
"name": "perfect-scrollbar",
"title": "perfect-scrollbar",
"description": "Tiny but perfect jquery scrollbar plugin.",
"version": "0.5.4",
"version": "0.5.9",
"author": {
"name": "Hyunje Alex Jun",
"email": "me@noraesae.net",

View File

@@ -1,99 +1,118 @@
.ps-container>.ps-scrollbar-x-rail {
position: absolute; /* please don't change 'position' */
bottom: 3px; /* there must be 'bottom' for ps-scrollbar-x-rail */
height: 8px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
opacity: 0;
filter: alpha(opacity=0);
-o-transition: background-color .2s linear, opacity .2s linear;
-webkit-transition: background-color .2s linear, opacity .2s linear;
-moz-transition: background-color .2s linear, opacity .2s linear;
transition: background-color .2s linear, opacity .2s linear;
}
.ps-container:hover>.ps-scrollbar-x-rail {
opacity: 0.6;
filter: alpha(opacity=60);
}
.ps-container>.ps-scrollbar-x-rail:hover {
.ps-container.ps-active-x > .ps-scrollbar-x-rail, .ps-container.ps-active-y > .ps-scrollbar-y-rail {
display: block; }
.ps-container.ps-in-scrolling {
pointer-events: none; }
.ps-container.ps-in-scrolling > .ps-scrollbar-x-rail {
background-color: #eee;
opacity: 0.9;
filter: alpha(opacity=90);
}
.ps-container>.ps-scrollbar-x-rail.in-scrolling {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: alpha(opacity=90); }
.ps-container.ps-in-scrolling > .ps-scrollbar-x-rail > .ps-scrollbar-x {
background-color: #999; }
.ps-container.ps-in-scrolling > .ps-scrollbar-y-rail {
background-color: #eee;
opacity: 0.9;
filter: alpha(opacity=90);
}
.ps-container>.ps-scrollbar-y-rail {
position: absolute; /* please don't change 'position' */
right: 3px; /* there must be 'right' for ps-scrollbar-y-rail */
width: 8px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
opacity: 0;
filter: alpha(opacity = 0);
-o-transition: background-color .2s linear, opacity .2s linear;
-webkit-transition: background-color .2s linear, opacity .2s linear;
-moz-transition: background-color .2s linear, opacity .2s linear;
transition: background-color .2s linear, opacity .2s linear;
}
.ps-container:hover>.ps-scrollbar-y-rail {
opacity: 0.6;
filter: alpha(opacity=60);
}
.ps-container>.ps-scrollbar-y-rail:hover {
background-color: #eee;
opacity: 0.9;
filter: alpha(opacity=90);
}
.ps-container>.ps-scrollbar-y-rail.in-scrolling {
background-color: #eee;
opacity: 0.9;
filter: alpha(opacity=90);
}
.ps-container>.ps-scrollbar-x-rail>.ps-scrollbar-x {
position: absolute; /* please don't change 'position' */
bottom: 0; /* there must be 'bottom' for ps-scrollbar-x */
height: 8px;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: alpha(opacity=90); }
.ps-container.ps-in-scrolling > .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' */
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
border-radius: 4px;
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
-webkit-transition: background-color 0.2s linear, opacity 0.2s linear;
-moz-transition: background-color 0.2s linear, opacity 0.2s linear;
-o-transition: background-color 0.2s linear, opacity 0.2s linear;
transition: background-color 0.2s linear, opacity 0.2s linear;
bottom: 3px;
/* there must be 'bottom' for ps-scrollbar-x-rail */
height: 8px; }
.ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x {
position: absolute;
/* please don't change 'position' */
background-color: #aaa;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
border-radius: 4px;
-o-transition: background-color .2s linear;
-webkit-transition: background-color.2s linear;
-moz-transition: background-color .2s linear;
transition: background-color .2s linear;
}
.ps-container>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x {
background-color: #999;
}
.ps-container>.ps-scrollbar-y-rail>.ps-scrollbar-y {
position: absolute; /* please don't change 'position' */
right: 0; /* there must be 'right' for ps-scrollbar-y */
width: 8px;
-webkit-transition: background-color 0.2s linear;
-moz-transition: background-color 0.2s linear;
-o-transition: background-color 0.2s linear;
transition: background-color 0.2s linear;
bottom: 0;
/* there must be 'bottom' for ps-scrollbar-x */
height: 8px; }
.ps-container > .ps-scrollbar-y-rail {
display: none;
position: absolute;
/* please don't change 'position' */
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
border-radius: 4px;
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
-webkit-transition: background-color 0.2s linear, opacity 0.2s linear;
-moz-transition: background-color 0.2s linear, opacity 0.2s linear;
-o-transition: background-color 0.2s linear, opacity 0.2s linear;
transition: background-color 0.2s linear, opacity 0.2s linear;
right: 3px;
/* there must be 'right' for ps-scrollbar-y-rail */
width: 8px; }
.ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y {
position: absolute;
/* please don't change 'position' */
background-color: #aaa;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
border-radius: 4px;
-o-transition: background-color .2s linear;
-webkit-transition: background-color.2s linear;
-moz-transition: background-color .2s linear;
transition: background-color .2s linear;
}
.ps-container>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y {
background-color: #999;
}
-webkit-transition: background-color 0.2s linear;
-moz-transition: background-color 0.2s linear;
-o-transition: background-color 0.2s linear;
transition: background-color 0.2s linear;
right: 0;
/* there must be 'right' for ps-scrollbar-y */
width: 8px; }
.ps-container:hover.ps-in-scrolling {
pointer-events: none; }
.ps-container:hover.ps-in-scrolling > .ps-scrollbar-x-rail {
background-color: #eee;
opacity: 0.9;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: alpha(opacity=90); }
.ps-container:hover.ps-in-scrolling > .ps-scrollbar-x-rail > .ps-scrollbar-x {
background-color: #999; }
.ps-container:hover.ps-in-scrolling > .ps-scrollbar-y-rail {
background-color: #eee;
opacity: 0.9;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: alpha(opacity=90); }
.ps-container:hover.ps-in-scrolling > .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;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
filter: alpha(opacity=60); }
.ps-container:hover > .ps-scrollbar-x-rail:hover {
background-color: #eee;
opacity: 0.9;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: alpha(opacity=90); }
.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;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: alpha(opacity=90); }
.ps-container:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y {
background-color: #999; }

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2012, 2014 Hyunje Alex Jun and other contributors
/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
* Licensed under the MIT License
*/
(function (factory) {
@@ -17,7 +17,7 @@
})(function ($) {
'use strict';
function int(x) {
function getInt(x) {
if (typeof x === 'string') {
return parseInt(x, 10);
} else {
@@ -28,6 +28,7 @@
var defaultSettings = {
wheelSpeed: 1,
wheelPropagation: false,
swipePropagation: true,
minScrollbarLength: null,
maxScrollbarLength: null,
useBothWheelAxes: false,
@@ -39,20 +40,27 @@
includePadding: false
};
var getEventClassName = (function () {
var incrementingId = 0;
return function () {
var id = incrementingId;
incrementingId += 1;
return '.perfect-scrollbar-' + id;
var incrementingId = 0;
var eventClassFactory = function () {
var id = incrementingId++;
return function (eventName) {
var className = '.perfect-scrollbar-' + id;
if (typeof eventName === 'undefined') {
return className;
} else {
return eventName + className;
}
};
})();
};
var isWebkit = 'WebkitAppearance' in document.documentElement.style;
$.fn.perfectScrollbar = function (suppliedSettings, option) {
return this.each(function () {
var settings = $.extend(true, {}, defaultSettings);
var $this = $(this);
var isPluginAlive = function () { return !!$this; };
if (typeof suppliedSettings === "object") {
// Override default settings with any supplied
@@ -92,7 +100,7 @@
var contentHeight;
var isRtl = $this.css('direction') === "rtl";
var eventClassName = getEventClassName();
var eventClass = eventClassFactory();
var ownerDocument = this.ownerDocument || document;
var $scrollbarXRail = $("<div class='ps-scrollbar-x-rail'>").appendTo($this);
@@ -100,20 +108,24 @@
var scrollbarXActive;
var scrollbarXWidth;
var scrollbarXLeft;
var scrollbarXBottom = int($scrollbarXRail.css('bottom'));
var scrollbarXBottom = getInt($scrollbarXRail.css('bottom'));
var isScrollbarXUsingBottom = scrollbarXBottom === scrollbarXBottom; // !isNaN
var scrollbarXTop = isScrollbarXUsingBottom ? null : int($scrollbarXRail.css('top'));
var railBorderXWidth = int($scrollbarXRail.css('borderLeftWidth')) + int($scrollbarXRail.css('borderRightWidth'));
var scrollbarXTop = isScrollbarXUsingBottom ? null : getInt($scrollbarXRail.css('top'));
var railBorderXWidth = getInt($scrollbarXRail.css('borderLeftWidth')) + getInt($scrollbarXRail.css('borderRightWidth'));
var railXMarginWidth = getInt($scrollbarXRail.css('marginLeft')) + getInt($scrollbarXRail.css('marginRight'));
var railXWidth;
var $scrollbarYRail = $("<div class='ps-scrollbar-y-rail'>").appendTo($this);
var $scrollbarY = $("<div class='ps-scrollbar-y'>").appendTo($scrollbarYRail);
var scrollbarYActive;
var scrollbarYHeight;
var scrollbarYTop;
var scrollbarYRight = int($scrollbarYRail.css('right'));
var scrollbarYRight = getInt($scrollbarYRail.css('right'));
var isScrollbarYUsingRight = scrollbarYRight === scrollbarYRight; // !isNaN
var scrollbarYLeft = isScrollbarYUsingRight ? null : int($scrollbarYRail.css('left'));
var railBorderYWidth = int($scrollbarXRail.css('borderTopWidth')) + int($scrollbarXRail.css('borderBottomWidth'));
var scrollbarYLeft = isScrollbarYUsingRight ? null : getInt($scrollbarYRail.css('left'));
var railBorderYWidth = getInt($scrollbarYRail.css('borderTopWidth')) + getInt($scrollbarYRail.css('borderBottomWidth'));
var railYMarginHeight = getInt($scrollbarYRail.css('marginTop')) + getInt($scrollbarYRail.css('marginBottom'));
var railYHeight;
function updateScrollTop(currentTop, deltaY) {
var newTop = currentTop + deltaY;
@@ -127,7 +139,7 @@
scrollbarYTop = newTop;
}
var scrollTop = int(scrollbarYTop * (contentHeight - containerHeight) / (containerHeight - scrollbarYHeight));
var scrollTop = getInt(scrollbarYTop * (contentHeight - containerHeight) / (containerHeight - scrollbarYHeight));
$this.scrollTop(scrollTop);
}
@@ -143,7 +155,7 @@
scrollbarXLeft = newLeft;
}
var scrollLeft = int(scrollbarXLeft * (contentWidth - containerWidth) / (containerWidth - scrollbarXWidth));
var scrollLeft = getInt(scrollbarXLeft * (contentWidth - containerWidth) / (containerWidth - scrollbarXWidth));
$this.scrollLeft(scrollLeft);
}
@@ -158,7 +170,7 @@
}
function updateCss() {
var xRailOffset = {width: containerWidth, display: scrollbarXActive ? "inherit" : "none"};
var xRailOffset = {width: railXWidth};
if (isRtl) {
xRailOffset.left = $this.scrollLeft() + containerWidth - contentWidth;
} else {
@@ -171,7 +183,7 @@
}
$scrollbarXRail.css(xRailOffset);
var railYOffset = {top: $this.scrollTop(), height: containerHeight, display: scrollbarYActive ? "inherit" : "none"};
var railYOffset = {top: $this.scrollTop(), height: railYHeight};
if (isScrollbarYUsingRight) {
if (isRtl) {
@@ -194,8 +206,8 @@
function updateGeometry() {
// Hide scrollbars not to affect scrollWidth and scrollHeight
$scrollbarXRail.hide();
$scrollbarYRail.hide();
$this.removeClass('ps-active-x');
$this.removeClass('ps-active-y');
containerWidth = settings.includePadding ? $this.innerWidth() : $this.width();
containerHeight = settings.includePadding ? $this.innerHeight() : $this.height();
@@ -204,8 +216,9 @@
if (!settings.suppressScrollX && containerWidth + settings.scrollXMarginOffset < contentWidth) {
scrollbarXActive = true;
scrollbarXWidth = getThumbSize(int(containerWidth * containerWidth / contentWidth));
scrollbarXLeft = int($this.scrollLeft() * (containerWidth - scrollbarXWidth) / (contentWidth - containerWidth));
railXWidth = containerWidth - railXMarginWidth;
scrollbarXWidth = getThumbSize(getInt(railXWidth * containerWidth / contentWidth));
scrollbarXLeft = getInt($this.scrollLeft() * (railXWidth - scrollbarXWidth) / (contentWidth - containerWidth));
} else {
scrollbarXActive = false;
scrollbarXWidth = 0;
@@ -215,8 +228,9 @@
if (!settings.suppressScrollY && containerHeight + settings.scrollYMarginOffset < contentHeight) {
scrollbarYActive = true;
scrollbarYHeight = getThumbSize(int(containerHeight * containerHeight / contentHeight));
scrollbarYTop = int($this.scrollTop() * (containerHeight - scrollbarYHeight) / (contentHeight - containerHeight));
railYHeight = containerHeight - railYMarginHeight;
scrollbarYHeight = getThumbSize(getInt(railYHeight * containerHeight / contentHeight));
scrollbarYTop = getInt($this.scrollTop() * (railYHeight - scrollbarYHeight) / (contentHeight - containerHeight));
} else {
scrollbarYActive = false;
scrollbarYHeight = 0;
@@ -224,33 +238,20 @@
$this.scrollTop(0);
}
if (scrollbarXLeft >= containerWidth - scrollbarXWidth) {
scrollbarXLeft = containerWidth - scrollbarXWidth;
if (scrollbarXLeft >= railXWidth - scrollbarXWidth) {
scrollbarXLeft = railXWidth - scrollbarXWidth;
}
if (scrollbarYTop >= containerHeight - scrollbarYHeight) {
scrollbarYTop = containerHeight - scrollbarYHeight;
if (scrollbarYTop >= railYHeight - scrollbarYHeight) {
scrollbarYTop = railYHeight - scrollbarYHeight;
}
updateCss();
if (scrollbarXActive) {
$this.addClass('ps-active-x');
} else {
$this.removeClass('ps-active-x');
}
if (scrollbarYActive) {
$this.addClass('ps-active-y');
} else {
$this.removeClass('ps-active-y');
}
// Show scrollbars if needed after updated
if (!settings.suppressScrollX) {
$scrollbarXRail.show();
}
if (!settings.suppressScrollY) {
$scrollbarYRail.show();
}
}
@@ -258,27 +259,28 @@
var currentLeft;
var currentPageX;
$scrollbarX.bind('mousedown' + eventClassName, function (e) {
currentPageX = e.pageX;
currentLeft = $scrollbarX.position().left;
$scrollbarXRail.addClass('in-scrolling');
var mouseMoveHandler = function (e) {
updateScrollLeft(currentLeft, e.pageX - currentPageX);
updateGeometry();
e.stopPropagation();
e.preventDefault();
});
};
$(ownerDocument).bind('mousemove' + eventClassName, function (e) {
if ($scrollbarXRail.hasClass('in-scrolling')) {
updateScrollLeft(currentLeft, e.pageX - currentPageX);
updateGeometry();
e.stopPropagation();
e.preventDefault();
}
});
var mouseUpHandler = function (e) {
$this.removeClass('ps-in-scrolling');
$(ownerDocument).unbind(eventClass('mousemove'), mouseMoveHandler);
};
$(ownerDocument).bind('mouseup' + eventClassName, function (e) {
if ($scrollbarXRail.hasClass('in-scrolling')) {
$scrollbarXRail.removeClass('in-scrolling');
}
$scrollbarX.bind(eventClass('mousedown'), function (e) {
currentPageX = e.pageX;
currentLeft = $scrollbarX.position().left;
$this.addClass('ps-in-scrolling');
$(ownerDocument).bind(eventClass('mousemove'), mouseMoveHandler);
$(ownerDocument).one(eventClass('mouseup'), mouseUpHandler);
e.stopPropagation();
e.preventDefault();
});
currentLeft =
@@ -289,35 +291,35 @@
var currentTop;
var currentPageY;
$scrollbarY.bind('mousedown' + eventClassName, function (e) {
currentPageY = e.pageY;
currentTop = $scrollbarY.position().top;
$scrollbarYRail.addClass('in-scrolling');
var mouseMoveHandler = function (e) {
updateScrollTop(currentTop, e.pageY - currentPageY);
updateGeometry();
e.stopPropagation();
e.preventDefault();
});
};
$(ownerDocument).bind('mousemove' + eventClassName, function (e) {
if ($scrollbarYRail.hasClass('in-scrolling')) {
updateScrollTop(currentTop, e.pageY - currentPageY);
updateGeometry();
e.stopPropagation();
e.preventDefault();
}
});
var mouseUpHandler = function (e) {
$this.removeClass('ps-in-scrolling');
$(ownerDocument).unbind(eventClass('mousemove'), mouseMoveHandler);
};
$(ownerDocument).bind('mouseup' + eventClassName, function (e) {
if ($scrollbarYRail.hasClass('in-scrolling')) {
$scrollbarYRail.removeClass('in-scrolling');
}
$scrollbarY.bind(eventClass('mousedown'), function (e) {
currentPageY = e.pageY;
currentTop = $scrollbarY.position().top;
$this.addClass('ps-in-scrolling');
$(ownerDocument).bind(eventClass('mousemove'), mouseMoveHandler);
$(ownerDocument).one(eventClass('mouseup'), mouseUpHandler);
e.stopPropagation();
e.preventDefault();
});
currentTop =
currentPageY = null;
}
// check if the default scrolling should be prevented.
function shouldPreventDefault(deltaX, deltaY) {
function shouldPreventWheel(deltaX, deltaY) {
var scrollTop = $this.scrollTop();
if (deltaX === 0) {
if (!scrollbarYActive) {
@@ -340,6 +342,31 @@
return true;
}
function shouldPreventSwipe(deltaX, deltaY) {
var scrollTop = $this.scrollTop();
var scrollLeft = $this.scrollLeft();
var magnitudeX = Math.abs(deltaX);
var magnitudeY = Math.abs(deltaY);
if (magnitudeY > magnitudeX) {
// user is perhaps trying to swipe up/down the page
if (((deltaY < 0) && (scrollTop === contentHeight - containerHeight)) ||
((deltaY > 0) && (scrollTop === 0))) {
return !settings.swipePropagation;
}
} else if (magnitudeX > magnitudeY) {
// user is perhaps trying to swipe left/right across the page
if (((deltaX < 0) && (scrollLeft === contentWidth - containerWidth)) ||
((deltaX > 0) && (scrollLeft === 0))) {
return !settings.swipePropagation;
}
}
return true;
}
function bindMouseWheelHandler() {
var shouldPrevent = false;
@@ -369,6 +396,13 @@
}
function mousewheelHandler(e) {
// FIXME: this is a quick fix for the select problem in FF and IE.
// If there comes an effective way to deal with the problem,
// this lines should be removed.
if (!isWebkit && $this.find('select:focus').length > 0) {
return;
}
var delta = getDeltaFromEvent(e);
var deltaX = delta[0];
@@ -402,7 +436,7 @@
updateGeometry();
shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
shouldPrevent = (shouldPrevent || shouldPreventWheel(deltaX, deltaY));
if (shouldPrevent) {
e.stopPropagation();
e.preventDefault();
@@ -410,23 +444,23 @@
}
if (typeof window.onwheel !== "undefined") {
$this.bind('wheel' + eventClassName, mousewheelHandler);
$this.bind(eventClass('wheel'), mousewheelHandler);
} else if (typeof window.onmousewheel !== "undefined") {
$this.bind('mousewheel' + eventClassName, mousewheelHandler);
$this.bind(eventClass('mousewheel'), mousewheelHandler);
}
}
function bindKeyboardHandler() {
var hovered = false;
$this.bind('mouseenter' + eventClassName, function (e) {
$this.bind(eventClass('mouseenter'), function (e) {
hovered = true;
});
$this.bind('mouseleave' + eventClassName, function (e) {
$this.bind(eventClass('mouseleave'), function (e) {
hovered = false;
});
var shouldPrevent = false;
$(ownerDocument).bind('keydown' + eventClassName, function (e) {
$(ownerDocument).bind(eventClass('keydown'), function (e) {
if (e.isDefaultPrevented && e.isDefaultPrevented()) {
return;
}
@@ -436,12 +470,15 @@
}
var activeElement = document.activeElement ? document.activeElement : ownerDocument.activeElement;
// go deeper if element is a webcomponent
while (activeElement.shadowRoot) {
activeElement = activeElement.shadowRoot.activeElement;
}
if ($(activeElement).is(":input,[contenteditable]")) {
return;
if (activeElement) {
// go deeper if element is a webcomponent
while (activeElement.shadowRoot) {
activeElement = activeElement.shadowRoot.activeElement;
}
if ($(activeElement).is(":input,[contenteditable]")) {
return;
}
}
var deltaX = 0;
@@ -488,7 +525,7 @@
$this.scrollTop($this.scrollTop() - deltaY);
$this.scrollLeft($this.scrollLeft() + deltaX);
shouldPrevent = shouldPreventDefault(deltaX, deltaY);
shouldPrevent = shouldPreventWheel(deltaX, deltaY);
if (shouldPrevent) {
e.preventDefault();
}
@@ -498,9 +535,9 @@
function bindRailClickHandler() {
function stopPropagation(e) { e.stopPropagation(); }
$scrollbarY.bind('click' + eventClassName, stopPropagation);
$scrollbarYRail.bind('click' + eventClassName, function (e) {
var halfOfScrollbarLength = int(scrollbarYHeight / 2);
$scrollbarY.bind(eventClass('click'), stopPropagation);
$scrollbarYRail.bind(eventClass('click'), function (e) {
var halfOfScrollbarLength = getInt(scrollbarYHeight / 2);
var positionTop = e.pageY - $scrollbarYRail.offset().top - halfOfScrollbarLength;
var maxPositionTop = containerHeight - scrollbarYHeight;
var positionRatio = positionTop / maxPositionTop;
@@ -514,9 +551,9 @@
$this.scrollTop((contentHeight - containerHeight) * positionRatio);
});
$scrollbarX.bind('click' + eventClassName, stopPropagation);
$scrollbarXRail.bind('click' + eventClassName, function (e) {
var halfOfScrollbarLength = int(scrollbarXWidth / 2);
$scrollbarX.bind(eventClass('click'), stopPropagation);
$scrollbarXRail.bind(eventClass('click'), function (e) {
var halfOfScrollbarLength = getInt(scrollbarXWidth / 2);
var positionLeft = e.pageX - $scrollbarXRail.offset().left - halfOfScrollbarLength;
var maxPositionLeft = containerWidth - scrollbarXWidth;
var positionRatio = positionLeft / maxPositionLeft;
@@ -531,6 +568,106 @@
});
}
function bindSelectionHandler() {
function getRangeNode() {
var selection = window.getSelection ? window.getSelection() :
document.getSlection ? document.getSlection() : {rangeCount: 0};
if (selection.rangeCount === 0) {
return null;
} else {
return selection.getRangeAt(0).commonAncestorContainer;
}
}
var scrollingLoop = null;
var scrollDiff = {top: 0, left: 0};
function startScrolling() {
if (!scrollingLoop) {
scrollingLoop = setInterval(function () {
if (!isPluginAlive()) {
clearInterval(scrollingLoop);
return;
}
$this.scrollTop($this.scrollTop() + scrollDiff.top);
$this.scrollLeft($this.scrollLeft() + scrollDiff.left);
updateGeometry();
}, 50); // every .1 sec
}
}
function stopScrolling() {
if (scrollingLoop) {
clearInterval(scrollingLoop);
scrollingLoop = null;
}
$this.removeClass('ps-in-scrolling');
$this.removeClass('ps-in-scrolling');
}
var isSelected = false;
$(ownerDocument).bind(eventClass('selectionchange'), function (e) {
if ($.contains($this[0], getRangeNode())) {
isSelected = true;
} else {
isSelected = false;
stopScrolling();
}
});
$(window).bind(eventClass('mouseup'), function (e) {
if (isSelected) {
isSelected = false;
stopScrolling();
}
});
$(window).bind(eventClass('mousemove'), function (e) {
if (isSelected) {
var mousePosition = {x: e.pageX, y: e.pageY};
var containerOffset = $this.offset();
var containerGeometry = {
left: containerOffset.left,
right: containerOffset.left + $this.outerWidth(),
top: containerOffset.top,
bottom: containerOffset.top + $this.outerHeight()
};
if (mousePosition.x < containerGeometry.left + 3) {
scrollDiff.left = -5;
$this.addClass('ps-in-scrolling');
} else if (mousePosition.x > containerGeometry.right - 3) {
scrollDiff.left = 5;
$this.addClass('ps-in-scrolling');
} else {
scrollDiff.left = 0;
}
if (mousePosition.y < containerGeometry.top + 3) {
if (containerGeometry.top + 3 - mousePosition.y < 5) {
scrollDiff.top = -5;
} else {
scrollDiff.top = -20;
}
$this.addClass('ps-in-scrolling');
} else if (mousePosition.y > containerGeometry.bottom - 3) {
if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
scrollDiff.top = 5;
} else {
scrollDiff.top = 20;
}
$this.addClass('ps-in-scrolling');
} else {
scrollDiff.top = 0;
}
if (scrollDiff.top === 0 && scrollDiff.left === 0) {
stopScrolling();
} else {
startScrolling();
}
}
});
}
function bindTouchHandler(supportsTouch, supportsIePointer) {
function applyTouchMove(differenceX, differenceY) {
$this.scrollTop($this.scrollTop() - differenceY);
@@ -542,8 +679,9 @@
var startOffset = {};
var startTime = 0;
var speed = {};
var breakingProcess = null;
var easingLoop = null;
var inGlobalTouch = false;
var inLocalTouch = false;
function globalTouchStart(e) {
inGlobalTouch = true;
@@ -560,23 +698,36 @@
return e.originalEvent;
}
}
function touchStart(e) {
var touch = getTouch(e);
startOffset.pageX = touch.pageX;
startOffset.pageY = touch.pageY;
startTime = (new Date()).getTime();
if (breakingProcess !== null) {
clearInterval(breakingProcess);
function shouldHandle(e) {
var event = e.originalEvent;
if (event.targetTouches && event.targetTouches.length === 1) {
return true;
}
if (event.pointerType && event.pointerType !== 'mouse' && event.pointerType !== event.MSPOINTER_TYPE_MOUSE) {
return true;
}
return false;
}
function touchStart(e) {
if (shouldHandle(e)) {
inLocalTouch = true;
e.stopPropagation();
e.preventDefault();
var touch = getTouch(e);
startOffset.pageX = touch.pageX;
startOffset.pageY = touch.pageY;
startTime = (new Date()).getTime();
if (easingLoop !== null) {
clearInterval(easingLoop);
}
e.stopPropagation();
}
}
function touchMove(e) {
if (!inGlobalTouch && e.originalEvent.targetTouches.length === 1) {
if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
var touch = getTouch(e);
var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
@@ -596,60 +747,71 @@
startTime = currentTime;
}
e.stopPropagation();
e.preventDefault();
if (shouldPreventSwipe(differenceX, differenceY)) {
e.stopPropagation();
e.preventDefault();
}
}
}
function touchEnd(e) {
clearInterval(breakingProcess);
breakingProcess = setInterval(function () {
if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
clearInterval(breakingProcess);
return;
}
if (!inGlobalTouch && inLocalTouch) {
inLocalTouch = false;
applyTouchMove(speed.x * 30, speed.y * 30);
clearInterval(easingLoop);
easingLoop = setInterval(function () {
if (!isPluginAlive()) {
clearInterval(easingLoop);
return;
}
speed.x *= 0.8;
speed.y *= 0.8;
}, 10);
if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
clearInterval(easingLoop);
return;
}
applyTouchMove(speed.x * 30, speed.y * 30);
speed.x *= 0.8;
speed.y *= 0.8;
}, 10);
}
}
if (supportsTouch) {
$(window).bind("touchstart" + eventClassName, globalTouchStart);
$(window).bind("touchend" + eventClassName, globalTouchEnd);
$this.bind("touchstart" + eventClassName, touchStart);
$this.bind("touchmove" + eventClassName, touchMove);
$this.bind("touchend" + eventClassName, touchEnd);
$(window).bind(eventClass("touchstart"), globalTouchStart);
$(window).bind(eventClass("touchend"), globalTouchEnd);
$this.bind(eventClass("touchstart"), touchStart);
$this.bind(eventClass("touchmove"), touchMove);
$this.bind(eventClass("touchend"), touchEnd);
}
if (supportsIePointer) {
if (window.PointerEvent) {
$(window).bind("pointerdown" + eventClassName, globalTouchStart);
$(window).bind("pointerup" + eventClassName, globalTouchEnd);
$this.bind("pointerdown" + eventClassName, touchStart);
$this.bind("pointermove" + eventClassName, touchMove);
$this.bind("pointerup" + eventClassName, touchEnd);
$(window).bind(eventClass("pointerdown"), globalTouchStart);
$(window).bind(eventClass("pointerup"), globalTouchEnd);
$this.bind(eventClass("pointerdown"), touchStart);
$this.bind(eventClass("pointermove"), touchMove);
$this.bind(eventClass("pointerup"), touchEnd);
} else if (window.MSPointerEvent) {
$(window).bind("MSPointerDown" + eventClassName, globalTouchStart);
$(window).bind("MSPointerUp" + eventClassName, globalTouchEnd);
$this.bind("MSPointerDown" + eventClassName, touchStart);
$this.bind("MSPointerMove" + eventClassName, touchMove);
$this.bind("MSPointerUp" + eventClassName, touchEnd);
$(window).bind(eventClass("MSPointerDown"), globalTouchStart);
$(window).bind(eventClass("MSPointerUp"), globalTouchEnd);
$this.bind(eventClass("MSPointerDown"), touchStart);
$this.bind(eventClass("MSPointerMove"), touchMove);
$this.bind(eventClass("MSPointerUp"), touchEnd);
}
}
}
function bindScrollHandler() {
$this.bind('scroll' + eventClassName, function (e) {
$this.bind(eventClass('scroll'), function (e) {
updateGeometry();
});
}
function destroy() {
$this.unbind(eventClassName);
$(window).unbind(eventClassName);
$(ownerDocument).unbind(eventClassName);
$this.unbind(eventClass());
$(window).unbind(eventClass());
$(ownerDocument).unbind(eventClass());
$this.data('perfect-scrollbar', null);
$this.data('perfect-scrollbar-update', null);
$this.data('perfect-scrollbar-destroy', null);
@@ -659,6 +821,7 @@
$scrollbarYRail.remove();
// clean all variables
$this =
$scrollbarXRail =
$scrollbarYRail =
$scrollbarX =
@@ -680,7 +843,7 @@
isScrollbarYUsingRight =
scrollbarYLeft =
isRtl =
eventClassName = null;
eventClass = null;
}
var supportsTouch = (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
@@ -692,6 +855,7 @@
bindMouseScrollXHandler();
bindMouseScrollYHandler();
bindRailClickHandler();
bindSelectionHandler();
bindMouseWheelHandler();
if (supportsTouch || supportsIePointer) {

127
src/perfect-scrollbar.scss Normal file
View File

@@ -0,0 +1,127 @@
// Colors
$ps-rail-hover: #eee;
$ps-bar-default: #aaa;
$ps-bar-hover: #999;
// Helper mixins
@mixin opacity($o) {
$IEValue: $o * 100;
opacity: $o;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity="+$IEValue+")";
filter: alpha(opacity=$IEValue);
}
@mixin border-radius($r) {
-webkit-border-radius: $r;
-moz-border-radius: $r;
-ms-border-radius: $r;
border-radius: $r;
}
@mixin transition($t...) {
-webkit-transition: $t;
-moz-transition: $t;
-o-transition: $t;
transition: $t;
}
// Scrollbar mixins
@mixin scrollbar-rail-default {
display: none;
position: absolute; /* please don't change 'position' */
@include border-radius(4px);
@include opacity(0);
@include transition(background-color .2s linear, opacity .2s linear);
}
@mixin scrollbar-rail-hover {
background-color: $ps-rail-hover;
@include opacity(0.9);
}
@mixin scrollbar-default {
position: absolute; /* please don't change 'position' */
background-color: $ps-bar-default;
@include border-radius(4px);
@include transition(background-color .2s linear);
}
@mixin scrollbar-hover {
background-color: $ps-bar-hover;
}
@mixin in-scrolling {
&.ps-in-scrolling {
pointer-events: none;
>.ps-scrollbar-x-rail {
@include scrollbar-rail-hover;
>.ps-scrollbar-x {
@include scrollbar-hover;
}
}
>.ps-scrollbar-y-rail {
@include scrollbar-rail-hover;
>.ps-scrollbar-y {
@include scrollbar-hover;
}
}
}
}
.ps-container {
&.ps-active-x > .ps-scrollbar-x-rail,
&.ps-active-y > .ps-scrollbar-y-rail {
display: block;
}
@include in-scrolling;
>.ps-scrollbar-x-rail {
@include scrollbar-rail-default;
bottom: 3px; /* there must be 'bottom' for ps-scrollbar-x-rail */
height: 8px;
>.ps-scrollbar-x {
@include scrollbar-default;
bottom: 0; /* there must be 'bottom' for ps-scrollbar-x */
height: 8px;
}
}
>.ps-scrollbar-y-rail {
@include scrollbar-rail-default;
right: 3px; /* there must be 'right' for ps-scrollbar-y-rail */
width: 8px;
>.ps-scrollbar-y {
@include scrollbar-default;
right: 0; /* there must be 'right' for ps-scrollbar-y */
width: 8px;
}
}
&:hover {
@include in-scrolling;
>.ps-scrollbar-x-rail,
>.ps-scrollbar-y-rail {
@include opacity(0.6);
}
>.ps-scrollbar-x-rail:hover {
@include scrollbar-rail-hover;
>.ps-scrollbar-x {
@include scrollbar-hover;
}
}
>.ps-scrollbar-y-rail:hover {
@include scrollbar-rail-hover;
>.ps-scrollbar-y {
@include scrollbar-hover;
}
}
}
}