Compare commits

...

40 Commits
0.5.2 ... 0.5.7

Author SHA1 Message Date
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
Hyunje Alex Jun
a98c77d160 Release 0.5.4
1. Inner scrollbar problem fix.
2. Inner scrollbar touch event problem fix.
3. Bug fixes.
2014-10-21 21:31:02 +01:00
Hyunje Alex Jun
48e1c688b2 Add additional information to package.json 2014-10-21 21:29:34 +01:00
Hyunje Alex Jun
991e664b18 Stop propagation and prevent default for touch events.
Fix #228.
2014-10-21 21:14:23 +01:00
Hyunje Alex Jun
ee4fc96b7a Bind touch handlers only when it's supported.
Fix #227.
2014-10-21 21:06:16 +01:00
Hyunje Alex Jun
664dec23d6 No longer support old IEs. 2014-10-21 20:58:43 +01:00
Hyunje Alex Jun
65869821c1 Use > CSS selector.
This patch will resolve inner scrollbar problems.
2014-10-21 20:53:55 +01:00
Hyunje Alex Jun
4f7595a34f Release 0.5.3.
1. Focusable element bug fix for ShadowDom element.
2. Int conversion enhancement.
3. Add IE Pointer handler.
4. Ctrl+Home/End support.
5. Iframe support.
2014-10-14 01:38:04 +01:00
Hyunje Alex Jun
97a44c29a8 Add grunt task to release new version. 2014-10-14 01:37:05 +01:00
Nicolás Moncada
467cdb17ed Adding an example using iframe. 2014-10-14 01:11:06 +01:00
Nicolás Moncada
6ac02fae2b It makes compatible with iframes. 2014-10-14 01:11:06 +01:00
Hyunje Alex Jun
d4ec7fca6d Merge pull request #219 from MathieuLorber/input-in-shadowdom
ShadowDom form elements are considered for preventing scrolling by keyevent
2014-10-14 01:46:03 +02:00
Gene Diaz Jr
0022bd5595 Added cdn information
mirror on cdnjs.com http://cdnjs.com/libraries/jquery.perfect-scrollbar

Modified by @noraesae, as I wouldn't want to update README every time
I bump up the version.
2014-10-14 00:39:09 +01:00
Hyunje Alex Jun
1b1195288b Add ctrl key support for keyboard handler.
Originally written by @wikenator.
2014-10-14 00:29:51 +01:00
loliver
e6590da884 IE Pointer Events
Added support for PointerEvents (and MSPointerEvents) to support touch
in IE10 and 11.

Modified by @noraesae.
2014-10-14 00:13:04 +01:00
Hyunje Alex Jun
e98bfec4f2 Remove IE6 specific fixes.
Just don't use IE6.
2014-10-13 23:47:47 +01:00
Hyunje Alex Jun
f7d90464e0 More code refactoring.
It's never enough.
2014-10-13 23:47:47 +01:00
Hyunje Alex Jun
337c0be9e2 Add int() helper instead of parseInt.
parseInt is a good option for string-int conversion,
but none for float-int conversion because of performance issue.

This is also to make the code clean.
2014-10-13 23:24:20 +01:00
Hyunje Alex Jun
36c988faba Code refactoring. 2014-10-13 23:24:20 +01:00
Mathieu Lorber
a573d2cd9d ShadowDom form elements are considered for preventing scrolling by keyevent 2014-10-01 11:49:16 +02:00
Hyunje Alex Jun
f231110f21 Merge pull request #217 from josemalonsom/patch-1
Minor corrections in example.
2014-09-29 21:54:11 +01:00
josemalonsom
503b05f5ae Minor corrections in example.
Just a couple of minor corrections in the CSS of the example "How to use".
2014-09-29 22:18:05 +02:00
14 changed files with 794 additions and 455 deletions

View File

@@ -27,7 +27,7 @@
"asi" : false,
"laxbreak" : false,
"bitwise" : true,
"bitwise" : false,
"boss" : false,
"curly" : true,
"eqeqeq" : true,

View File

@@ -1,13 +1,13 @@
'use strict';
module.exports = function (grunt) {
require('load-grunt-tasks')(grunt);
// Project configuration.
grunt.initConfig({
// Metadata.
pkg: grunt.file.readJSON('perfect-scrollbar.jquery.json'),
version: grunt.file.readJSON('package.json').version,
banner: '/*! <%= pkg.title || pkg.name %> - v<%= version %>\n' +
banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %>\n' +
'<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
@@ -39,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 %>'
@@ -59,16 +50,25 @@ module.exports = function (grunt) {
dest: 'min/',
ext: '.min.css'
}
},
bump: {
options: {
files: ['package.json', 'bower.json', 'perfect-scrollbar.jquery.json'],
updateConfigs: ['pkg'],
commit: false,
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.registerTask('default', 'List commands', function () {
grunt.log.writeln("");
@@ -76,8 +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

@@ -44,16 +44,24 @@ You can download the latest stable version with download links in [Github 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).
Requirements
------------
@@ -125,8 +133,8 @@ How to Use
```html
<style>
#Demo {
position: 'relative';
height: 100%; // Or whatever you want (eg. 400px)
position: relative;
height: 100%; /* Or whatever you want (eg. 400px) */
overflow: hidden;
}
</style>
@@ -184,11 +192,9 @@ For IE problems, please refer to [IE Support](https://github.com/noraesae/perfec
IE Support
----------
This plugin supports old IE browsers in the **minimum** range. The plugin is tested in IEs >= IE6 and works(not well, but works).
The plugin would work in IEs >= IE9(not well, though).
**But the project will not accept the patches to fix IE problems in IE 6/7/8.**
From jQuery 2.0, jQuery also will not support IE 6/7/8. I also think that supporting old browsers really breaks the web development conventions.
**The patches to fix problems in IE<=8 won't be accepted.**
When old IEs should be supported, please fork the project and make patches personally.
@@ -197,6 +203,8 @@ 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 the problems frequently asked, there's a [FAQ](https://github.com/noraesae/perfect-scrollbar/wiki/FAQ) wiki page. Please check the page before uploading an issue.
License
-------

View File

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

View File

@@ -0,0 +1,20 @@
<!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">
<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 }
</style>
</head>
<body>
<div id="Default" class="contentHolder">
<div class="content">
</div>
</div>
</body>
</html>

27
examples/iframe.html Normal file
View File

@@ -0,0 +1,27 @@
<!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>
#iframe { width: 100%; min-height: 450px; border: 0; }
html { direction: rtl; }
</style>
<script>
jQuery(document).ready(function ($) {
"use strict";
$('#iframe').load(function() {
var contentIframe = $(this).contents();
var documentIframe = contentIframe.get(0);
$('#Default', documentIframe).perfectScrollbar();
});
});
</script>
</head>
<body>
<iframe src="iframe-content.html" id="iframe"></iframe>
</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

@@ -1,5 +1,5 @@
/*! perfect-scrollbar - v0.5.2
/*! perfect-scrollbar - v0.5.7
* http://noraesae.github.com/perfect-scrollbar/
* Copyright (c) 2014 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,.ps-container.hover .ps-scrollbar-x-rail{opacity:.6;filter:alpha(opacity=60)}.ps-container .ps-scrollbar-x-rail:hover,.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,.ps-container.hover .ps-scrollbar-y-rail{opacity:.6;filter:alpha(opacity=60)}.ps-container .ps-scrollbar-y-rail:hover,.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{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.ie6 .ps-scrollbar-x{font-size:0}.ps-container .ps-scrollbar-x-rail:hover .ps-scrollbar-x,.ps-container .ps-scrollbar-x-rail.hover .ps-scrollbar-x{background-color:#999}.ps-container .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.ie6 .ps-scrollbar-y{font-size:0}.ps-container .ps-scrollbar-y-rail:hover .ps-scrollbar-y,.ps-container .ps-scrollbar-y-rail.hover .ps-scrollbar-y{background-color:#999}.ps-container.ie .ps-scrollbar-x,.ps-container.ie .ps-scrollbar-y{visibility:hidden}.ps-container.ie:hover .ps-scrollbar-x,.ps-container.ie:hover .ps-scrollbar-y,.ps-container.ie.hover .ps-scrollbar-x,.ps-container.ie.hover .ps-scrollbar-y{visibility:visible}
.ps-container.ps-active-x>.ps-scrollbar-x-rail,.ps-container.ps-active-y>.ps-scrollbar-y-rail{display:block}.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-x-rail.in-scrolling{background-color:#eee;opacity:.9;-ms-filter:"alpha(Opacity=90)";filter:alpha(opacity=90)}.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>.ps-scrollbar-y-rail.in-scrolling{background-color:#eee;opacity:.9;-ms-filter:"alpha(Opacity=90)";filter:alpha(opacity=90)}.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.in-scrolling,.ps-container:hover>.ps-scrollbar-y-rail.in-scrolling{background-color:#eee;opacity:.9;-ms-filter:"alpha(Opacity=90)";filter:alpha(opacity=90)}.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,19 +1,43 @@
{
"name": "perfect-scrollbar",
"version": "0.5.2",
"version": "0.5.7",
"description": "Tiny but perfect jquery scrollbar plugin.",
"author": "Hyunje Alex Jun <me@noraesae.net>",
"contributors": [
{
"name": "Hyunje Alex Jun",
"email": "me@noraesae.net"
}
],
"main": "src/perfect-scrollbar.js",
"repository": {
"type": "git",
"url": "https://github.com/noraesae/perfect-scrollbar"
},
"bugs": {
"url": "https://github.com/noraesae/perfect-scrollbar/issues"
},
"keywords": [
"jquery-plugin",
"scroll",
"scrollbar"
],
"engines": {
"node": ">= 0.8.0"
},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-bump": "0.0.16",
"grunt-contrib-clean": "~0.4.1",
"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-cssmin": "~0.6.1",
"grunt-contrib-csslint": "~0.1.2",
"grunt-contrib-clean": "~0.4.1"
"grunt-sass": "^0.16.1",
"load-grunt-tasks": "^1.0.0"
},
"scripts": {
"test": "grunt travis --verbose"
}
},
"license": "MIT"
}

View File

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

View File

@@ -1,125 +1,101 @@
.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,
.ps-container.hover .ps-scrollbar-x-rail {
opacity: 0.6;
filter: alpha(opacity=60);
}
.ps-container .ps-scrollbar-x-rail:hover,
.ps-container .ps-scrollbar-x-rail.hover {
background-color: #eee;
opacity: 0.9;
filter: alpha(opacity=90);
}
.ps-container .ps-scrollbar-x-rail.in-scrolling {
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,
.ps-container.hover .ps-scrollbar-y-rail {
opacity: 0.6;
filter: alpha(opacity=60);
}
.ps-container .ps-scrollbar-y-rail:hover,
.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 {
position: absolute; /* please don't change 'position' */
bottom: 0; /* there must be 'bottom' for ps-scrollbar-x */
height: 8px;
.ps-container.ps-active-x > .ps-scrollbar-x-rail, .ps-container.ps-active-y > .ps-scrollbar-y-rail {
display: block; }
.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.ie6 .ps-scrollbar-x {
font-size: 0; /* fixed scrollbar height in xp sp3 ie6 */
}
.ps-container .ps-scrollbar-x-rail:hover .ps-scrollbar-x,
.ps-container .ps-scrollbar-x-rail.hover .ps-scrollbar-x {
background-color: #999;
}
.ps-container .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-x-rail.in-scrolling {
background-color: #eee;
opacity: 0.9;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: alpha(opacity=90); }
.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.ie6 .ps-scrollbar-y {
font-size: 0; /* fixed scrollbar height in xp sp3 ie6 */
}
.ps-container .ps-scrollbar-y-rail:hover .ps-scrollbar-y,
.ps-container .ps-scrollbar-y-rail.hover .ps-scrollbar-y {
background-color: #999;
}
.ps-container.ie .ps-scrollbar-x,
.ps-container.ie .ps-scrollbar-y {
visibility: hidden;
}
.ps-container.ie:hover .ps-scrollbar-x,
.ps-container.ie:hover .ps-scrollbar-y,
.ps-container.ie.hover .ps-scrollbar-x,
.ps-container.ie.hover .ps-scrollbar-y {
visibility: visible;
}
-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 > .ps-scrollbar-y-rail.in-scrolling {
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, .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.in-scrolling, .ps-container:hover > .ps-scrollbar-y-rail.in-scrolling {
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 {
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

@@ -14,10 +14,17 @@
// Browser globals
factory(jQuery);
}
}(function ($) {
})(function ($) {
'use strict';
// The default settings for the plugin
function int(x) {
if (typeof x === 'string') {
return parseInt(x, 10);
} else {
return ~~x;
}
}
var defaultSettings = {
wheelSpeed: 1,
wheelPropagation: false,
@@ -32,32 +39,35 @@
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;
}
};
}());
};
$.fn.perfectScrollbar = function (suppliedSettings, option) {
return this.each(function () {
// Use the default settings
var settings = $.extend(true, {}, defaultSettings),
$this = $(this);
var settings = $.extend(true, {}, defaultSettings);
var $this = $(this);
var isPluginAlive = function () { return !!$this; };
if (typeof suppliedSettings === "object") {
// But over-ride any supplied
// Override default settings with any supplied
$.extend(true, settings, suppliedSettings);
} else {
// If no settings were supplied, then the first param must be the option
// If no setting was supplied, then the first param must be the option
option = suppliedSettings;
}
// Catch options
if (option === 'update') {
if ($this.data('perfect-scrollbar-update')) {
$this.data('perfect-scrollbar-update')();
@@ -79,71 +89,70 @@
// Or generate new perfectScrollbar
// Set class to the container
$this.addClass('ps-container');
var $scrollbarXRail = $("<div class='ps-scrollbar-x-rail'></div>").appendTo($this),
$scrollbarYRail = $("<div class='ps-scrollbar-y-rail'></div>").appendTo($this),
$scrollbarX = $("<div class='ps-scrollbar-x'></div>").appendTo($scrollbarXRail),
$scrollbarY = $("<div class='ps-scrollbar-y'></div>").appendTo($scrollbarYRail),
scrollbarXActive,
scrollbarYActive,
containerWidth,
containerHeight,
contentWidth,
contentHeight,
scrollbarXWidth,
scrollbarXLeft,
scrollbarXBottom = parseInt($scrollbarXRail.css('bottom'), 10),
isScrollbarXUsingBottom = scrollbarXBottom === scrollbarXBottom, // !isNaN
scrollbarXTop = isScrollbarXUsingBottom ? null : parseInt($scrollbarXRail.css('top'), 10),
scrollbarYHeight,
scrollbarYTop,
scrollbarYRight = parseInt($scrollbarYRail.css('right'), 10),
isScrollbarYUsingRight = scrollbarYRight === scrollbarYRight, // !isNaN
scrollbarYLeft = isScrollbarYUsingRight ? null: parseInt($scrollbarYRail.css('left'), 10),
isRtl = $this.css('direction') === "rtl",
eventClassName = getEventClassName(),
railBorderXWidth = parseInt($scrollbarXRail.css('borderLeftWidth'), 10) + parseInt($scrollbarXRail.css('borderRightWidth'), 10),
railBorderYWidth = parseInt($scrollbarXRail.css('borderTopWidth'), 10) + parseInt($scrollbarXRail.css('borderBottomWidth'), 10);
var containerWidth;
var containerHeight;
var contentWidth;
var contentHeight;
var updateContentScrollTop = function (currentTop, deltaY) {
var newTop = currentTop + deltaY,
maxTop = containerHeight - scrollbarYHeight;
var isRtl = $this.css('direction') === "rtl";
var eventClass = eventClassFactory();
var ownerDocument = this.ownerDocument || document;
var $scrollbarXRail = $("<div class='ps-scrollbar-x-rail'>").appendTo($this);
var $scrollbarX = $("<div class='ps-scrollbar-x'>").appendTo($scrollbarXRail);
var scrollbarXActive;
var scrollbarXWidth;
var scrollbarXLeft;
var scrollbarXBottom = int($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 $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 isScrollbarYUsingRight = scrollbarYRight === scrollbarYRight; // !isNaN
var scrollbarYLeft = isScrollbarYUsingRight ? null : int($scrollbarYRail.css('left'));
var railBorderYWidth = int($scrollbarYRail.css('borderTopWidth')) + int($scrollbarYRail.css('borderBottomWidth'));
function updateScrollTop(currentTop, deltaY) {
var newTop = currentTop + deltaY;
var maxTop = containerHeight - scrollbarYHeight;
if (newTop < 0) {
scrollbarYTop = 0;
}
else if (newTop > maxTop) {
} else if (newTop > maxTop) {
scrollbarYTop = maxTop;
}
else {
} else {
scrollbarYTop = newTop;
}
var scrollTop = parseInt(scrollbarYTop * (contentHeight - containerHeight) / (containerHeight - scrollbarYHeight), 10);
var scrollTop = int(scrollbarYTop * (contentHeight - containerHeight) / (containerHeight - scrollbarYHeight));
$this.scrollTop(scrollTop);
};
}
var updateContentScrollLeft = function (currentLeft, deltaX) {
var newLeft = currentLeft + deltaX,
maxLeft = containerWidth - scrollbarXWidth;
function updateScrollLeft(currentLeft, deltaX) {
var newLeft = currentLeft + deltaX;
var maxLeft = containerWidth - scrollbarXWidth;
if (newLeft < 0) {
scrollbarXLeft = 0;
}
else if (newLeft > maxLeft) {
} else if (newLeft > maxLeft) {
scrollbarXLeft = maxLeft;
}
else {
} else {
scrollbarXLeft = newLeft;
}
var scrollLeft = parseInt(scrollbarXLeft * (contentWidth - containerWidth) / (containerWidth - scrollbarXWidth), 10);
var scrollLeft = int(scrollbarXLeft * (contentWidth - containerWidth) / (containerWidth - scrollbarXWidth));
$this.scrollLeft(scrollLeft);
};
}
var getSettingsAdjustedThumbSize = function (thumbSize) {
function getThumbSize(thumbSize) {
if (settings.minScrollbarLength) {
thumbSize = Math.max(thumbSize, settings.minScrollbarLength);
}
@@ -151,59 +160,47 @@
thumbSize = Math.min(thumbSize, settings.maxScrollbarLength);
}
return thumbSize;
};
}
var updateScrollbarCss = function () {
var scrollbarXStyles = {width: containerWidth, display: scrollbarXActive ? "inherit": "none"};
function updateCss() {
var xRailOffset = {width: containerWidth};
if (isRtl) {
scrollbarXStyles.left = $this.scrollLeft() + containerWidth - contentWidth;
xRailOffset.left = $this.scrollLeft() + containerWidth - contentWidth;
} else {
scrollbarXStyles.left = $this.scrollLeft();
xRailOffset.left = $this.scrollLeft();
}
if (isScrollbarXUsingBottom) {
scrollbarXStyles.bottom = scrollbarXBottom - $this.scrollTop();
xRailOffset.bottom = scrollbarXBottom - $this.scrollTop();
} else {
scrollbarXStyles.top = scrollbarXTop + $this.scrollTop();
xRailOffset.top = scrollbarXTop + $this.scrollTop();
}
$scrollbarXRail.css(scrollbarXStyles);
$scrollbarXRail.css(xRailOffset);
var scrollbarYStyles = {top: $this.scrollTop(), height: containerHeight, display: scrollbarYActive ? "inherit": "none"};
var railYOffset = {top: $this.scrollTop(), height: containerHeight};
if (isScrollbarYUsingRight) {
if (isRtl) {
scrollbarYStyles.right = contentWidth - $this.scrollLeft() - scrollbarYRight - $scrollbarY.outerWidth();
railYOffset.right = contentWidth - $this.scrollLeft() - scrollbarYRight - $scrollbarY.outerWidth();
} else {
scrollbarYStyles.right = scrollbarYRight - $this.scrollLeft();
railYOffset.right = scrollbarYRight - $this.scrollLeft();
}
} else {
if (isRtl) {
scrollbarYStyles.left = $this.scrollLeft() + containerWidth * 2 - contentWidth - scrollbarYLeft - $scrollbarY.outerWidth();
railYOffset.left = $this.scrollLeft() + containerWidth * 2 - contentWidth - scrollbarYLeft - $scrollbarY.outerWidth();
} else {
scrollbarYStyles.left = scrollbarYLeft + $this.scrollLeft();
railYOffset.left = scrollbarYLeft + $this.scrollLeft();
}
}
$scrollbarYRail.css(scrollbarYStyles);
$scrollbarYRail.css(railYOffset);
$scrollbarX.css({left: scrollbarXLeft, width: scrollbarXWidth - railBorderXWidth});
$scrollbarY.css({top: scrollbarYTop, height: scrollbarYHeight - railBorderYWidth});
}
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');
}
};
var updateBarSizeAndPosition = function () {
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();
@@ -212,10 +209,9 @@
if (!settings.suppressScrollX && containerWidth + settings.scrollXMarginOffset < contentWidth) {
scrollbarXActive = true;
scrollbarXWidth = getSettingsAdjustedThumbSize(parseInt(containerWidth * containerWidth / contentWidth, 10));
scrollbarXLeft = parseInt($this.scrollLeft() * (containerWidth - scrollbarXWidth) / (contentWidth - containerWidth), 10);
}
else {
scrollbarXWidth = getThumbSize(int(containerWidth * containerWidth / contentWidth));
scrollbarXLeft = int($this.scrollLeft() * (containerWidth - scrollbarXWidth) / (contentWidth - containerWidth));
} else {
scrollbarXActive = false;
scrollbarXWidth = 0;
scrollbarXLeft = 0;
@@ -224,98 +220,102 @@
if (!settings.suppressScrollY && containerHeight + settings.scrollYMarginOffset < contentHeight) {
scrollbarYActive = true;
scrollbarYHeight = getSettingsAdjustedThumbSize(parseInt(containerHeight * containerHeight / contentHeight, 10));
scrollbarYTop = parseInt($this.scrollTop() * (containerHeight - scrollbarYHeight) / (contentHeight - containerHeight), 10);
}
else {
scrollbarYHeight = getThumbSize(int(containerHeight * containerHeight / contentHeight));
scrollbarYTop = int($this.scrollTop() * (containerHeight - scrollbarYHeight) / (contentHeight - containerHeight));
} else {
scrollbarYActive = false;
scrollbarYHeight = 0;
scrollbarYTop = 0;
$this.scrollTop(0);
}
if (scrollbarYTop >= containerHeight - scrollbarYHeight) {
scrollbarYTop = containerHeight - scrollbarYHeight;
}
if (scrollbarXLeft >= containerWidth - scrollbarXWidth) {
scrollbarXLeft = containerWidth - scrollbarXWidth;
}
updateScrollbarCss();
// Show scrollbars if needed after updated
if (!settings.suppressScrollX) {
$scrollbarXRail.show();
if (scrollbarYTop >= containerHeight - scrollbarYHeight) {
scrollbarYTop = containerHeight - scrollbarYHeight;
}
if (!settings.suppressScrollY) {
$scrollbarYRail.show();
updateCss();
if (scrollbarXActive) {
$this.addClass('ps-active-x');
}
};
if (scrollbarYActive) {
$this.addClass('ps-active-y');
}
}
var bindMouseScrollXHandler = function () {
var currentLeft,
currentPageX;
function bindMouseScrollXHandler() {
var currentLeft;
var currentPageX;
$scrollbarX.bind('mousedown' + eventClassName, function (e) {
var inScrolling = false;
$scrollbarX.bind(eventClass('mousedown'), function (e) {
currentPageX = e.pageX;
currentLeft = $scrollbarX.position().left;
$scrollbarXRail.addClass('in-scrolling');
inScrolling = true;
e.stopPropagation();
e.preventDefault();
});
$(document).bind('mousemove' + eventClassName, function (e) {
if ($scrollbarXRail.hasClass('in-scrolling')) {
updateContentScrollLeft(currentLeft, e.pageX - currentPageX);
updateBarSizeAndPosition();
$(ownerDocument).bind(eventClass('mousemove'), function (e) {
if (inScrolling) {
updateScrollLeft(currentLeft, e.pageX - currentPageX);
updateGeometry();
e.stopPropagation();
e.preventDefault();
}
});
$(document).bind('mouseup' + eventClassName, function (e) {
if ($scrollbarXRail.hasClass('in-scrolling')) {
$(ownerDocument).bind(eventClass('mouseup'), function (e) {
if (inScrolling) {
inScrolling = false;
$scrollbarXRail.removeClass('in-scrolling');
}
});
currentLeft =
currentPageX = null;
};
}
var bindMouseScrollYHandler = function () {
var currentTop,
currentPageY;
function bindMouseScrollYHandler() {
var currentTop;
var currentPageY;
$scrollbarY.bind('mousedown' + eventClassName, function (e) {
var inScrolling = false;
$scrollbarY.bind(eventClass('mousedown'), function (e) {
currentPageY = e.pageY;
currentTop = $scrollbarY.position().top;
inScrolling = true;
$scrollbarYRail.addClass('in-scrolling');
e.stopPropagation();
e.preventDefault();
});
$(document).bind('mousemove' + eventClassName, function (e) {
if ($scrollbarYRail.hasClass('in-scrolling')) {
updateContentScrollTop(currentTop, e.pageY - currentPageY);
updateBarSizeAndPosition();
$(ownerDocument).bind(eventClass('mousemove'), function (e) {
if (inScrolling) {
updateScrollTop(currentTop, e.pageY - currentPageY);
updateGeometry();
e.stopPropagation();
e.preventDefault();
}
});
$(document).bind('mouseup' + eventClassName, function (e) {
if ($scrollbarYRail.hasClass('in-scrolling')) {
$(ownerDocument).bind(eventClass('mouseup'), function (e) {
if (inScrolling) {
inScrolling = false;
$scrollbarYRail.removeClass('in-scrolling');
}
});
currentTop =
currentPageY = null;
};
}
// check if the default scrolling should be prevented.
var shouldPreventDefault = function (deltaX, deltaY) {
function shouldPreventDefault(deltaX, deltaY) {
var scrollTop = $this.scrollTop();
if (deltaX === 0) {
if (!scrollbarYActive) {
@@ -336,15 +336,14 @@
}
}
return true;
};
}
// bind handlers
var bindMouseWheelHandler = function () {
function bindMouseWheelHandler() {
var shouldPrevent = false;
var getDeltaFromEvent = function (e) {
var deltaX = e.originalEvent.deltaX,
deltaY = -1 * e.originalEvent.deltaY;
function getDeltaFromEvent(e) {
var deltaX = e.originalEvent.deltaX;
var deltaY = -1 * e.originalEvent.deltaY;
if (typeof deltaX === "undefined" || typeof deltaY === "undefined") {
// OS X Safari
@@ -365,13 +364,13 @@
}
return [deltaX, deltaY];
};
}
var mousewheelHandler = function (e) {
function mousewheelHandler(e) {
var delta = getDeltaFromEvent(e);
var deltaX = delta[0],
deltaY = delta[1];
var deltaX = delta[0];
var deltaY = delta[1];
shouldPrevent = false;
if (!settings.useBothWheelAxes) {
@@ -399,44 +398,52 @@
shouldPrevent = true;
}
// update bar position
updateBarSizeAndPosition();
updateGeometry();
shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
if (shouldPrevent) {
e.stopPropagation();
e.preventDefault();
}
};
}
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);
}
};
}
var bindKeyboardHandler = function () {
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;
$(document).bind('keydown' + eventClassName, function (e) {
$(ownerDocument).bind(eventClass('keydown'), function (e) {
if (e.isDefaultPrevented && e.isDefaultPrevented()) {
return;
}
if (!hovered || $(document.activeElement).is(":input,[contenteditable]")) {
if (!hovered) {
return;
}
var deltaX = 0,
deltaY = 0;
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;
}
var deltaX = 0;
var deltaY = 0;
switch (e.which) {
case 37: // left
@@ -459,10 +466,18 @@
deltaY = -90;
break;
case 35: // end
deltaY = -containerHeight;
if (e.ctrlKey) {
deltaY = -contentHeight;
} else {
deltaY = -containerHeight;
}
break;
case 36: // home
deltaY = containerHeight;
if (e.ctrlKey) {
deltaY = $this.scrollTop();
} else {
deltaY = containerHeight;
}
break;
default:
return;
@@ -476,17 +491,17 @@
e.preventDefault();
}
});
};
}
var bindRailClickHandler = function () {
var stopPropagation = function (e) { e.stopPropagation(); };
function bindRailClickHandler() {
function stopPropagation(e) { e.stopPropagation(); }
$scrollbarY.bind('click' + eventClassName, stopPropagation);
$scrollbarYRail.bind('click' + eventClassName, function (e) {
var halfOfScrollbarLength = parseInt(scrollbarYHeight / 2, 10),
positionTop = e.pageY - $scrollbarYRail.offset().top - halfOfScrollbarLength,
maxPositionTop = containerHeight - scrollbarYHeight,
positionRatio = positionTop / maxPositionTop;
$scrollbarY.bind(eventClass('click'), stopPropagation);
$scrollbarYRail.bind(eventClass('click'), function (e) {
var halfOfScrollbarLength = int(scrollbarYHeight / 2);
var positionTop = e.pageY - $scrollbarYRail.offset().top - halfOfScrollbarLength;
var maxPositionTop = containerHeight - scrollbarYHeight;
var positionRatio = positionTop / maxPositionTop;
if (positionRatio < 0) {
positionRatio = 0;
@@ -497,12 +512,12 @@
$this.scrollTop((contentHeight - containerHeight) * positionRatio);
});
$scrollbarX.bind('click' + eventClassName, stopPropagation);
$scrollbarXRail.bind('click' + eventClassName, function (e) {
var halfOfScrollbarLength = parseInt(scrollbarXWidth / 2, 10),
positionLeft = e.pageX - $scrollbarXRail.offset().left - halfOfScrollbarLength,
maxPositionLeft = containerWidth - scrollbarXWidth,
positionRatio = positionLeft / maxPositionLeft;
$scrollbarX.bind(eventClass('click'), stopPropagation);
$scrollbarXRail.bind(eventClass('click'), function (e) {
var halfOfScrollbarLength = int(scrollbarXWidth / 2);
var positionLeft = e.pageX - $scrollbarXRail.offset().left - halfOfScrollbarLength;
var maxPositionLeft = containerWidth - scrollbarXWidth;
var positionRatio = positionLeft / maxPositionLeft;
if (positionRatio < 0) {
positionRatio = 0;
@@ -512,58 +527,177 @@
$this.scrollLeft((contentWidth - containerWidth) * positionRatio);
});
};
}
// bind mobile touch handler
var bindMobileTouchHandler = function () {
var applyTouchMove = function (differenceX, differenceY) {
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;
}
$scrollbarXRail.removeClass('in-scrolling');
$scrollbarYRail.removeClass('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;
$scrollbarXRail.addClass('in-scrolling');
} else if (mousePosition.x > containerGeometry.right - 3) {
scrollDiff.left = 5;
$scrollbarXRail.addClass('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;
}
$scrollbarYRail.addClass('in-scrolling');
} else if (mousePosition.y > containerGeometry.bottom - 3) {
if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
scrollDiff.top = 5;
} else {
scrollDiff.top = 20;
}
$scrollbarYRail.addClass('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);
$this.scrollLeft($this.scrollLeft() - differenceX);
// update bar position
updateBarSizeAndPosition();
};
updateGeometry();
}
var startCoords = {},
startTime = 0,
speed = {},
breakingProcess = null,
inGlobalTouch = false;
var startOffset = {};
var startTime = 0;
var speed = {};
var easingLoop = null;
var inGlobalTouch = false;
var inLocalTouch = false;
$(window).bind("touchstart" + eventClassName, function (e) {
function globalTouchStart(e) {
inGlobalTouch = true;
});
$(window).bind("touchend" + eventClassName, function (e) {
}
function globalTouchEnd(e) {
inGlobalTouch = false;
});
}
$this.bind("touchstart" + eventClassName, function (e) {
var touch = e.originalEvent.targetTouches[0];
startCoords.pageX = touch.pageX;
startCoords.pageY = touch.pageY;
startTime = (new Date()).getTime();
if (breakingProcess !== null) {
clearInterval(breakingProcess);
function getTouch(e) {
if (e.originalEvent.targetTouches) {
return e.originalEvent.targetTouches[0];
} else {
// Maybe IE pointer
return e.originalEvent;
}
}
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();
});
$this.bind("touchmove" + eventClassName, function (e) {
if (!inGlobalTouch && e.originalEvent.targetTouches.length === 1) {
var touch = e.originalEvent.targetTouches[0];
var touch = getTouch(e);
var currentCoords = {};
currentCoords.pageX = touch.pageX;
currentCoords.pageY = touch.pageY;
startOffset.pageX = touch.pageX;
startOffset.pageY = touch.pageY;
var differenceX = currentCoords.pageX - startCoords.pageX,
differenceY = currentCoords.pageY - startCoords.pageY;
startTime = (new Date()).getTime();
if (easingLoop !== null) {
clearInterval(easingLoop);
}
e.stopPropagation();
}
}
function touchMove(e) {
if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
var touch = getTouch(e);
var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
var differenceX = currentOffset.pageX - startOffset.pageX;
var differenceY = currentOffset.pageY - startOffset.pageY;
applyTouchMove(differenceX, differenceY);
startCoords = currentCoords;
startOffset = currentOffset;
var currentTime = (new Date()).getTime();
@@ -574,35 +708,69 @@
startTime = currentTime;
}
e.stopPropagation();
e.preventDefault();
}
}
function touchEnd(e) {
if (!inGlobalTouch && inLocalTouch) {
inLocalTouch = false;
clearInterval(easingLoop);
easingLoop = setInterval(function () {
if (!isPluginAlive()) {
clearInterval(easingLoop);
return;
}
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(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(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(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(eventClass('scroll'), function (e) {
updateGeometry();
});
$this.bind("touchend" + eventClassName, function (e) {
clearInterval(breakingProcess);
breakingProcess = setInterval(function () {
if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
clearInterval(breakingProcess);
return;
}
}
applyTouchMove(speed.x * 30, speed.y * 30);
speed.x *= 0.8;
speed.y *= 0.8;
}, 10);
});
};
var bindScrollHandler = function () {
$this.bind('scroll' + eventClassName, function (e) {
updateBarSizeAndPosition();
});
};
var destroy = function () {
$this.unbind(eventClassName);
$(window).unbind(eventClassName);
$(document).unbind(eventClassName);
function destroy() {
$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);
@@ -612,6 +780,7 @@
$scrollbarYRail.remove();
// clean all variables
$this =
$scrollbarXRail =
$scrollbarYRail =
$scrollbarX =
@@ -633,86 +802,35 @@
isScrollbarYUsingRight =
scrollbarYLeft =
isRtl =
eventClassName = null;
};
var ieSupport = function (version) {
$this.addClass('ie').addClass('ie' + version);
var bindHoverHandlers = function () {
var mouseenter = function () {
$(this).addClass('hover');
};
var mouseleave = function () {
$(this).removeClass('hover');
};
$this.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
$scrollbarXRail.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
$scrollbarYRail.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
$scrollbarX.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
$scrollbarY.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
};
var fixIe6ScrollbarPosition = function () {
updateScrollbarCss = function () {
var scrollbarXStyles = {left: scrollbarXLeft + $this.scrollLeft(), width: scrollbarXWidth};
if (isScrollbarXUsingBottom) {
scrollbarXStyles.bottom = scrollbarXBottom;
} else {
scrollbarXStyles.top = scrollbarXTop;
}
$scrollbarX.css(scrollbarXStyles);
var scrollbarYStyles = {top: scrollbarYTop + $this.scrollTop(), height: scrollbarYHeight};
if (isScrollbarYUsingRight) {
scrollbarYStyles.right = scrollbarYRight;
} else {
scrollbarYStyles.left = scrollbarYLeft;
}
$scrollbarY.css(scrollbarYStyles);
$scrollbarX.hide().show();
$scrollbarY.hide().show();
};
};
if (version === 6) {
bindHoverHandlers();
fixIe6ScrollbarPosition();
}
};
eventClass = null;
}
var supportsTouch = (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
var supportsIePointer = window.navigator.msMaxTouchPoints !== null;
var initialize = function () {
var ieMatch = navigator.userAgent.toLowerCase().match(/(msie) ([\w.]+)/);
if (ieMatch && ieMatch[1] === 'msie') {
// must be executed at first, because 'ieSupport' may addClass to the container
ieSupport(parseInt(ieMatch[2], 10));
}
updateBarSizeAndPosition();
function initialize() {
updateGeometry();
bindScrollHandler();
bindMouseScrollXHandler();
bindMouseScrollYHandler();
bindRailClickHandler();
bindSelectionHandler();
bindMouseWheelHandler();
if (supportsTouch) {
bindMobileTouchHandler();
if (supportsTouch || supportsIePointer) {
bindTouchHandler(supportsTouch, supportsIePointer);
}
if (settings.useKeyboard) {
bindKeyboardHandler();
}
$this.data('perfect-scrollbar', $this);
$this.data('perfect-scrollbar-update', updateBarSizeAndPosition);
$this.data('perfect-scrollbar-update', updateGeometry);
$this.data('perfect-scrollbar-destroy', destroy);
};
}
// initialize
initialize();
return $this;
});
};
}));
});

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

@@ -0,0 +1,111 @@
// 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: #eee;
@include opacity(0.9);
}
@mixin scrollbar-default {
position: absolute; /* please don't change 'position' */
background-color: #aaa;
@include border-radius(4px);
@include transition(background-color .2s linear);
}
@mixin scrollbar-hover {
background-color: #999;
}
@mixin in-scrolling {
&.in-scrolling {
@include scrollbar-rail-hover;
}
}
.ps-container {
&.ps-active-x > .ps-scrollbar-x-rail,
&.ps-active-y > .ps-scrollbar-y-rail {
display: block;
}
>.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;
}
@include in-scrolling;
}
>.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;
}
@include in-scrolling;
}
&:hover {
>.ps-scrollbar-x-rail,
>.ps-scrollbar-y-rail {
@include opacity(0.6);
@include in-scrolling;
}
>.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;
}
}
}
}