├── .gitignore ├── README.textile ├── Rakefile ├── build ├── jquery-custom-scrollbar-0.5.0.zip ├── jquery-custom-scrollbar-0.5.1.zip ├── jquery-custom-scrollbar-0.5.2.zip ├── jquery-custom-scrollbar-0.5.3.zip ├── jquery-custom-scrollbar-0.5.4.zip └── jquery-custom-scrollbar-0.5.5.zip ├── custom-scrollbar.jquery.json ├── demos ├── basic.html ├── events.html ├── expandable_list.html ├── images │ └── lena.png ├── index.html ├── nested.html ├── prevent_default_scroll.html ├── resizing.html ├── scrolling_programmatically.html └── skins.html ├── jquery.custom-scrollbar.css └── jquery.custom-scrollbar.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | npm-debug.log -------------------------------------------------------------------------------- /README.textile: -------------------------------------------------------------------------------- 1 | h1. jQuery Custom Scrollbar 2 | 3 | jQuery Custom Scrollbar is a jQuery plugin that lets you add fully customizable scrollbars to your sites. With the plugin you can apply any css styles you want to your scrollbars. 4 | 5 | h2. Features 6 | 7 | * vertical and horizontal scrollbars you can style your own way 8 | * scrolling by mouse dragging, mouse wheel, keyboard - just as you would with native browser scrollbar 9 | * touch scrolling on mobile devices (Android, iPhone and iPad) 10 | * a couple predefined skins showing you how to style scrollbars 11 | * simple api that lets you scroll programmatically and be notified about scroll events 12 | 13 | h2. Requirements 14 | 15 | The plugin supports all major browsers: Chrome, Firefox, IE 7+. 16 | 17 | To use the plugin you obviously need jQuery (it should work in jQuery 1.4 and later versions). 18 | 19 | h2. Download 20 | 21 | You can download the latest version "here":https://github.com/mzubala/jquery-custom-scrollbar/raw/master/build/jquery-custom-scrollbar-0.5.5.zip 22 | 23 | h2. Demos 24 | 25 | In demos folder of this repo, there are some example usages of custom scrollbar and its api. The demos are also available online "here":http://jquery-custom-scrollbar.rocketmind.pl/ 26 | 27 | h2. Usage 28 | 29 | First download and add jquery.custom-scrollbar.js and jquery.custom-scrollbar.css to your site. 30 | 31 | Suppose you have a container on your site with some lengthy content and you want to make it scrollable: 32 | 33 |

 34 | 
35 | 36 |
37 |
38 | 39 | Define it's width and height (below some example size is used): 40 | 41 |

 42 | .container {
 43 |   width: 300px; // you can also use max-width
 44 |   height: 400px; // you can also use max-height
 45 | }
 46 | 
47 | 48 | Add a skin class to your container: 49 | 50 |

 51 | 
52 | 53 |
54 |
55 | 56 | In the example we use default-skin. Plugin comes with two other predefined skins: gray-skin and modern-skin. You are not limited to that and you can style scrollbar your own way. 57 | 58 | Finally call this js code: 59 | 60 |

 61 | $(document).ready(function() {
 62 |   $(".container").customScrollbar();
 63 | });
 64 | 
65 | 66 | If container content does not fit in those sizes scrollbar will appear. 67 | 68 | The above method will add vertical scrollbar only. If you also want to add horizontal scrollbar, there is one more css step required: 69 | 70 |

 71 | .container .overview {
 72 |   width: 1000px;
 73 | }
 74 | 
75 | 76 | This defines example total width of the scrolled content (not just the width of the visible part as in previous step). 77 | 78 | h2. Options 79 | 80 | There are some options you can pass when initializing scrollbar: 81 | 82 | |_. Option |_. Type|_. Default value |_. Description | 83 | | animationSpeed | Number | 300 | Speed of the animation of programmatic scrolling. It's possible to edit it with setAnimationSpeed method. Animation speed equal to 0 means no animation.| 84 | | fixedThumbHeight | Number | undefined | By default thumb height (in case of vertical scrollbar) is calculated automatically depending on viewport and overview height but you can fix thumb height to your chosen pixel value by setting this option. Make sure to not set min-height in css if you set fixedThumbHeight because min-height has priority.| 85 | | fixedThumbWidth | Number | undefined | Option analogical to fixedThumbHeight but applied to thumbs of horizontal scrollbars.| 86 | | hScroll | Boolean | true | Indicates whether or not, horizontal scrollbar should be shown when it's necessary. | 87 | | preventDefaultScroll | Boolean | false | When the scrolling event occurs (e.g. down arrow key, mouse wheel) and it doesn't cause the scrollbar to move (e.g. because the scrollbar is in extreme position), the event is propagated further which will cause the parent container to scroll. If it does cause the scrollbar movement then such event is stopped from propagating further and the parent container won't scroll. This default behaviour can be changed by setting preventDefaultScroll: true. It will cause the custom scrollbar to always stop scrolling event propagation no matter if the scrollbar changed or didn't change its position.| 88 | | skin|String|undefined|A css skin class that will be added to the scrolled container. You can define it in html as well as here in options. Note that skin has to be defined in one of those ways.| 89 | | swipeSpeed|Number|1|Indicates how fast touch scroll should be. When you swipe your finger by x pixels the content will be scrolled by swipeSpeed * x pixels.| 90 | | updateOnWindowResize | Boolean | false | Indicates whether scrollbar should recalculate thumb size when window is resized. See demos/resize.html for an example.| 91 | | vScroll | Boolean | true | Same as above but applies to vertical scrollbar. | 92 | | wheelSpeed|Number|40|Indicates how fast mouse wheel scroll should be. When you make the smallest possible mouse wheel move, the content will be scrolled by wheelSpeed pixels.| 93 | 94 | For example: 95 | 96 |

 97 | $("#my-container").customScrollbar({
 98 |   skin: "default-skin", 
 99 |   hScroll: false,
100 |   updateOnWindowResize: true
101 |   })
102 | 
103 | 104 | h2. API 105 | 106 | There are some methods of the plugin you may want to call. 107 | 108 | h3. setAnimationSpeed(speed) 109 | 110 | Changes programmatic scroll animation speed to the passed speed - an integer indicating how many milliseconds the animation should last. 111 | 112 | It's also possible to set the animation speed upon plugin initialization. By default it equals 300. 113 | 114 | Note that you may use this method if want to have some scrolls animated and some without animation - to get rid of the animation just call it with 0. 115 | 116 |

117 | $(".container").customScrollbar("setAnimationSpeed", 200)
118 | 
119 | 120 | 121 | h3. scrollTo(element) 122 | 123 | Scrolls viewport to a given element inside scrolled content. An element might be jQuery object or a selector string. To control animation speed use animationSpeed initialization option. Example usage: 124 | 125 |

126 | $(".container").customScrollbar("scrollTo", "#some-element-inside-container")
127 | 
128 | 129 | h3. scrollToX(x) 130 | 131 | Sets horizontal scrollbar position to x pixels. x should be in range from 0 to scrolled content width. If it's outside that range, content will be scrolled to the start or to the end. To control animation speed use animationSpeed initialization option. 132 | 133 |

134 | $(".container").customScrollbar("scrollToX", 100)
135 | 
136 | 137 | h3. scrollToY(y) 138 | 139 | Sets vertical scrollbar position to y pixels. x should be in range from 0 to scrolled content height. If it's outside that range, content will be scrolled to the start or to the end. To control animation speed use animationSpeed initialization option. 140 | 141 |

142 | $(".container").customScrollbar("scrollToY", 200)
143 | 
144 | 145 | h3. scrollByX(x) 146 | 147 | Moves horizontal scrollbar by x pixels. x can be positive or negative. 148 | 149 |

150 | $(".container").customScrollbar("scrollByX", 100)
151 | 
152 | 153 | h3. scrollByY(y) 154 | 155 | Moves vertical scrollbar by y pixels. y can be positive or negative. 156 | 157 |

158 | $(".container").customScrollbar("scrollByY", 200)
159 | 
160 | 161 | h3. resize(keepPosition) 162 | 163 | Recalculates and sets sizes of all scrollbar components. Call this whenever your scrolled block changes its size and scrollbar becomes invalid. After you call it scrollbar is adjusted to new sizes of your block. 164 | 165 | Use keepPosition parameter to decide if the scrollbar should stay in the same position (keepPosition == true) or change position (keepPosition == true) so that the thumb position change is proportional to the size change. The first case is useful if your container changes size and you want to show exactly the same content that was visible before size change. The second case is useful when you're listening to window resize. 166 | 167 |

168 | $(".container").customScrollbar("resize", true)
169 | 
170 | 171 | h3. remove() 172 | 173 | Removes all the DOM changes and event bindings added by the plugin. 174 | 175 |

176 | $(".container").customScrollbar("remove")
177 | 
178 | 179 | h2. Events 180 | 181 | h3. customScroll 182 | 183 | Triggered whenever content is scrolled. Separate events are fired when vertical and horizontal scrollbar is moved. 184 | 185 |

186 | $(".container").on("customScroll", function(event, scrollData) {});
187 | 
188 | 189 | Handler function takes two arguments. event is standard jquery event object. scrollData is an object with 3 fields holding scroll specific information: 190 | * scrollPercent - floating point number in range 0.0 to 100.0 indicating percentage position of the scrollbar 191 | * scrollDirection - string that can take following 4 values: left, right, up, down - indicates what direction the scrollbar was moved in 192 | * scrollAxis - string indicating which scrollbar was moved: X for horizontal scrollbar and Y for vertical scrollbar 193 | 194 | You can also bind handler to that event when initializing scrollbar: 195 | 196 |

197 | $(".container").customScrollbar({
198 |   onCustomScroll: function(event, scrollData) {}
199 | });
200 | 
201 | 202 | h2. License 203 | 204 | The plugin is released under "MIT license":http://www.opensource.org/licenses/MIT. 205 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | task :default => [:build] 4 | 5 | task :build do 6 | Dir.mkdir("build") unless Dir.exists?("build") 7 | build_name = "jquery-custom-scrollbar-#{JSON.parse(File.open("custom-scrollbar.jquery.json").read)["version"]}" 8 | dest = "build/#{build_name}" 9 | FileUtils.rm_rf(dest) if Dir.exists?(dest) 10 | Dir.mkdir(dest) 11 | FileUtils.cp("jquery.custom-scrollbar.css", dest) 12 | FileUtils.cp("jquery.custom-scrollbar.js", dest) 13 | system("uglifyjs -m --comments all -o #{dest}/jquery.custom-scrollbar.min.js #{dest}/jquery.custom-scrollbar.js") 14 | Dir.chdir("build") 15 | system("zip -r #{build_name}.zip #{build_name}") 16 | FileUtils.rm_rf(build_name) 17 | end -------------------------------------------------------------------------------- /build/jquery-custom-scrollbar-0.5.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzubala/jquery-custom-scrollbar/25c187d7085de61fdedabb6e34bb64f000df8784/build/jquery-custom-scrollbar-0.5.0.zip -------------------------------------------------------------------------------- /build/jquery-custom-scrollbar-0.5.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzubala/jquery-custom-scrollbar/25c187d7085de61fdedabb6e34bb64f000df8784/build/jquery-custom-scrollbar-0.5.1.zip -------------------------------------------------------------------------------- /build/jquery-custom-scrollbar-0.5.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzubala/jquery-custom-scrollbar/25c187d7085de61fdedabb6e34bb64f000df8784/build/jquery-custom-scrollbar-0.5.2.zip -------------------------------------------------------------------------------- /build/jquery-custom-scrollbar-0.5.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzubala/jquery-custom-scrollbar/25c187d7085de61fdedabb6e34bb64f000df8784/build/jquery-custom-scrollbar-0.5.3.zip -------------------------------------------------------------------------------- /build/jquery-custom-scrollbar-0.5.4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzubala/jquery-custom-scrollbar/25c187d7085de61fdedabb6e34bb64f000df8784/build/jquery-custom-scrollbar-0.5.4.zip -------------------------------------------------------------------------------- /build/jquery-custom-scrollbar-0.5.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzubala/jquery-custom-scrollbar/25c187d7085de61fdedabb6e34bb64f000df8784/build/jquery-custom-scrollbar-0.5.5.zip -------------------------------------------------------------------------------- /custom-scrollbar.jquery.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"custom-scrollbar", 3 | "version":"0.5.5", 4 | "title":"jQuery Custom Scrollbar", 5 | "author":{ 6 | "name":"Maciej Zubala", 7 | "email":"maciej.zubala@rocketmind.pl", 8 | "url":"http://rocketmind.pl/" 9 | }, 10 | "licenses":[ 11 | { 12 | "type":"MIT", 13 | "url":"http://www.opensource.org/licenses/mit-license.php" 14 | } 15 | ], 16 | "docs":"https://github.com/mzubala/jquery-custom-scrollbar", 17 | "download":"https://github.com/mzubala/jquery-custom-scrollbar", 18 | "dependencies":{ 19 | "jquery":">=1.4" 20 | }, 21 | 22 | "description":"jQuery Custom Scrollbar is a plugin that lets you add fully customizable scrollbars to your sites instead of browser's default scrollbars. When using the plugin you can apply any css styles you want to your scrollbars. Features include: vertical and horizontal scrollbars you can style your own way, scrolling by mouse dragging, mouse wheel, keyboard – just as you would with native browser scrollbar, touch scrolling on mobile devices (Android, iPhone and iPad), a couple predefined skins showing you how to style scrollbars, simple api that lets you scroll programmatically.", 23 | "keywords":["ui", "scroll", "scrollbar"], 24 | "homepage":"https://github.com/mzubala/jquery-custom-scrollbar", 25 | "bugs":"https://github.com/mzubala/jquery-custom-scrollbar/issues", 26 | "demo":"http://jquery-custom-scrollbar.rocketmind.pl", 27 | "maintainers":[ 28 | { 29 | "name":"Maciej Zubala", 30 | "email":"maciej.zubala@rocketmind.pl", 31 | "url":"http://rocketmind.pl/" 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /demos/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JQuery Custom Scrollbar - basic usage demo 5 | 6 | 7 | 8 | 85 | 86 | 87 | 88 |

JQuery Custom Scrollbar - basic usage

89 | 90 | 91 |

Vertical scrollbar

92 | 93 | 94 |
95 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 96 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 97 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 98 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 99 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 100 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 101 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 102 | interdum massa nibh nec erat. 103 |
104 | 105 |

Horizontal scrollbar

106 | 107 |
108 | lena 109 | lena 110 | lena 111 | lena 112 | lena 113 | lena 114 | lena 115 | lena 116 | lena 117 | lena 118 |
119 | 120 |

Vertical and horizontal scrollbar

121 | 122 | 123 |
124 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 125 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 126 | Quisque 127 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 128 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 129 | tempus 130 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 131 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 132 | eget 133 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 134 | in 135 | interdum massa nibh nec erat. 136 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 137 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 138 | Quisque 139 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 140 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 141 | tempus 142 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 143 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 144 | eget 145 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 146 | in 147 | interdum massa nibh nec erat. 148 |
149 | 150 | 151 |

Min thumb size

152 | 153 | 154 |
155 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 156 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 157 | Quisque 158 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 159 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 160 | tempus 161 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 162 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 163 | eget 164 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 165 | in 166 | interdum massa nibh nec erat. 167 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 168 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 169 | Quisque 170 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 171 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 172 | tempus 173 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 174 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 175 | eget 176 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 177 | in 178 | interdum massa nibh nec erat. 179 |
180 | 181 |

Fixed thumb size

182 | 183 | 184 |
185 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 186 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 187 | Quisque 188 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 189 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 190 | tempus 191 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 192 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 193 | eget 194 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 195 | in 196 | interdum massa nibh nec erat. 197 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 198 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 199 | Quisque 200 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 201 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 202 | tempus 203 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 204 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 205 | eget 206 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 207 | in 208 | interdum massa nibh nec erat. 209 |
210 | 211 |

No scrollbar needed

212 | 213 |

When the content is short enough to fit the container, the scrollbar won't appear.

214 | 215 | 216 |
217 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 218 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 219 |
220 | 221 | 227 | 228 | -------------------------------------------------------------------------------- /demos/events.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JQuery Custom Scrollbar - basic usage demo 5 | 6 | 7 | 8 | 46 | 47 | 48 | 49 |

JQuery Custom Scrollbar - events demo

50 | 51 |

Vertical scrollbar

52 | 53 | 54 |
55 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 56 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 57 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 58 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 59 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 60 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 61 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 62 | interdum massa nibh nec erat. 63 |
64 | 65 |

66 | Scroll percent: 0%
67 | Scroll direction: -
68 | Scroll axis: 69 |

70 | 71 |

Horizontal scrollbar

72 | 73 |
74 | lena 75 | lena 76 | lena 77 | lena 78 | lena 79 | lena 80 | lena 81 | lena 82 | lena 83 | lena 84 |
85 | 86 |

87 | Scroll percent: 0%
88 | Scroll direction: -
89 | Scroll axis: 90 |

91 | 92 |

Vertical and horizontal scrollbar

93 | 94 | 95 |
96 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 97 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 98 | Quisque 99 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 100 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 101 | tempus 102 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 103 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 104 | eget 105 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 106 | in 107 | interdum massa nibh nec erat. 108 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 109 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 110 | Quisque 111 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 112 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 113 | tempus 114 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 115 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 116 | eget 117 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 118 | in 119 | interdum massa nibh nec erat. 120 |
121 | 122 |

123 | Scroll percent: 0%
124 | Scroll direction: -
125 | Scroll axis: 126 |

127 | 128 | 138 | 139 | -------------------------------------------------------------------------------- /demos/expandable_list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JQuery Custom Scrollbar - basic usage demo 5 | 6 | 7 | 8 | 25 | 26 | 27 | 28 |

JQuery Custom Scrollbar - list with expandable items demo

29 | 30 | 31 |
32 | 313 |
314 | 315 | 316 | 338 | 339 | -------------------------------------------------------------------------------- /demos/images/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mzubala/jquery-custom-scrollbar/25c187d7085de61fdedabb6e34bb64f000df8784/demos/images/lena.png -------------------------------------------------------------------------------- /demos/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JQuery Custom Scrollbar - demos 5 | 6 | 7 | 8 |

jQuery Custom Scrollbar - demos

9 | 10 |

Welcome to jQuery Custom Scrollbar demos site. We've prepared following demos for you:

11 | 21 |

Feel free to examine demos source code, so you know better how to use our plugin.

22 |

Sorry for the nasty looks. We just wanted to make it stupid simple ;)

23 | 24 | -------------------------------------------------------------------------------- /demos/nested.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JQuery Custom Scrollbar - nested scrollbar demo 5 | 6 | 7 | 8 | 24 | 25 | 26 | 27 |

JQuery Custom Scrollbar - nested scrollbar demo

28 | 29 |
30 |

This container has a scrollbar and contains other scrollable container

31 | 32 |
33 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 34 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 35 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 36 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 37 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 38 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 39 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 40 | interdum massa nibh nec erat. 41 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 42 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 43 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 44 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 45 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 46 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 47 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 48 | interdum massa nibh nec erat. 49 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 50 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 51 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 52 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 53 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 54 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 55 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 56 | interdum massa nibh nec erat. 57 | 58 | 59 |
60 |

And some more content...

61 | 62 |

63 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 64 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 65 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 66 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 67 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 68 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 69 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 70 | interdum massa nibh nec erat. 71 |

72 |
73 | 74 | 75 | 80 | 81 | -------------------------------------------------------------------------------- /demos/prevent_default_scroll.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JQuery Custom Scrollbar - basic usage demo 5 | 6 | 7 | 8 | 79 | 80 | 81 | 82 |

JQuery Custom Scrollbar - preventDefaultScroll flag usage

83 | 84 |

After setting preventDefaultScroll: true, when you scroll and reach the end of the scrollbar and keep 85 | scrolling nothing happens cause the scrolling event is not propagated. The default (preventDefaultScroll: 86 | false) behavior is different - after reaching the end scrolling events are propagated which may cause 87 | parent container to scroll when it has its own custom or native scrollbar. The default behavior can be observed in 88 | all other demos.

89 | 90 |

Vertical scrollbar

91 | 92 | 93 |
94 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 95 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 96 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 97 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 98 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 99 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 100 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 101 | interdum massa nibh nec erat. 102 |
103 | 104 |

Horizontal scrollbar

105 | 106 |
107 | lena 108 | lena 109 | lena 110 | lena 111 | lena 112 | lena 113 | lena 114 | lena 115 | lena 116 | lena 117 |
118 | 119 |

Vertical and horizontal scrollbar

120 | 121 | 122 |
123 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 124 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 125 | Quisque 126 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 127 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 128 | tempus 129 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 130 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 131 | eget 132 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 133 | in 134 | interdum massa nibh nec erat. 135 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 136 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 137 | Quisque 138 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 139 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 140 | tempus 141 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 142 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 143 | eget 144 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 145 | in 146 | interdum massa nibh nec erat. 147 |
148 | 149 | 150 |

Min thumb size

151 | 152 | 153 |
154 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 155 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 156 | Quisque 157 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 158 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 159 | tempus 160 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 161 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 162 | eget 163 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 164 | in 165 | interdum massa nibh nec erat. 166 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 167 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 168 | Quisque 169 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 170 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 171 | tempus 172 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 173 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 174 | eget 175 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 176 | in 177 | interdum massa nibh nec erat. 178 |
179 | 180 |

Fixed thumb size

181 | 182 | 183 |
184 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 185 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 186 | Quisque 187 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 188 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 189 | tempus 190 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 191 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 192 | eget 193 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 194 | in 195 | interdum massa nibh nec erat. 196 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 197 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 198 | Quisque 199 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 200 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 201 | tempus 202 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 203 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 204 | eget 205 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 206 | in 207 | interdum massa nibh nec erat. 208 |
209 | 210 | 216 | 217 | -------------------------------------------------------------------------------- /demos/resizing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JQuery Custom Scrollbar - resizing demo 5 | 6 | 7 | 8 | 28 | 29 | 30 |
31 |

JQuery Custom Scrollbar - resizing demo

32 | 33 |

Try resizing browser window to see how scrollbar adjusts its height.

34 | 35 |

36 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, lacinia 37 | in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque semper 38 | justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed posuere libero 39 | dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus metus leo non est. 40 | Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. Phasellus ornare, ante vitae 41 | consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget nisi. Praesent sodales velit 42 | quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in interdum massa nibh nec erat. 43 |

44 | 45 | 46 | 47 |

48 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, lacinia 49 | in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque semper 50 | justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed posuere libero 51 | dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus metus leo non est. 52 | Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. Phasellus ornare, ante vitae 53 | consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget nisi. Praesent sodales velit 54 | quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in interdum massa nibh nec erat. 55 |

56 | 57 | 58 | 59 |

60 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, lacinia 61 | in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque semper 62 | justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed posuere libero 63 | dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus metus leo non est. 64 | Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. Phasellus ornare, ante vitae 65 | consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget nisi. Praesent sodales velit 66 | quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in interdum massa nibh nec erat. 67 |

68 | 69 | 70 | 71 |

72 | 73 |

74 | 75 | 83 |
84 | 85 | -------------------------------------------------------------------------------- /demos/scrolling_programmatically.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JQuery Custom Scrollbar - scrolling programmatically 5 | 6 | 7 | 8 | 49 | 50 | 51 | 52 |

JQuery Custom Scrollbar - scrolling programmatically

53 | 54 |

Use buttons below to scroll programmatically to an element inside scrolled div

55 | 56 |

Vertical scrollbar

57 | 58 | 59 |
60 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 61 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 62 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 63 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 64 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 65 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 66 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 67 | interdum massa nibh nec erat. 68 |

Element to scroll to

69 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 70 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 71 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 72 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 73 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 74 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 75 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 76 | interdum massa nibh nec erat. 77 |
78 | 79 |

80 | 81 |

82 | 83 |

Horizontal scrollbar

84 | 85 |
86 | lena 87 | lena 88 | lena 89 | lena 90 | lena 91 | 92 |
94 | No Lena ;( 95 |
96 | lena 97 | lena 98 | lena 99 | lena 100 |
101 | 102 |

103 | 104 |

105 | 106 | 107 |

Vertical and horizontal scrollbar

108 | 109 | 110 |
111 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 112 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 113 | Quisque 114 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 115 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 116 | tempus 117 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 118 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 119 | eget 120 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 121 | in 122 | interdum massa nibh nec erat. 123 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 124 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. 125 | Quisque 126 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 127 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel 128 | tempus 129 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 130 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus 131 | eget 132 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, 133 | in 134 | interdum massa nibh nec erat. 135 |
136 | 137 |

138 | 139 |

140 | 141 |

Relative horizontal scroll

142 | 143 |
144 | lena 145 | lena 146 | lena 147 | lena 148 | lena 149 | lena 150 | lena 151 | lena 152 | lena 153 |
154 | 155 |

156 | 157 | 158 |

159 | 160 | 180 | 181 | -------------------------------------------------------------------------------- /demos/skins.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JQuery Custom Scrollbar - predefined skins 5 | 6 | 7 | 8 | 20 | 21 | 22 | 23 |

JQuery Custom Scrollbar - predefined skins

24 | 25 | 26 |

Default skin

27 | 28 |
29 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 30 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 31 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 32 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 33 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 34 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 35 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 36 | interdum massa nibh nec erat. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit 37 | a, scelerisque sed, 38 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 39 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 40 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 41 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 42 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 43 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 44 | interdum massa nibh nec erat. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit 45 | a, scelerisque sed, 46 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 47 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 48 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 49 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 50 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 51 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 52 | interdum massa nibh nec erat. 53 |
54 | 55 |

Gray skin

56 | 57 |
58 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 59 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 60 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 61 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 62 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 63 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 64 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 65 | interdum massa nibh nec erat. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit 66 | a, scelerisque sed, 67 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 68 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 69 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 70 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 71 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 72 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 73 | interdum massa nibh nec erat. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit 74 | a, scelerisque sed, 75 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 76 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 77 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 78 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 79 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 80 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 81 | interdum massa nibh nec erat. 82 |
83 | 84 |

Modern skin

85 | 86 |
87 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, 88 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 89 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 90 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 91 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 92 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 93 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 94 | interdum massa nibh nec erat. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit 95 | a, scelerisque sed, 96 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 97 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 98 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 99 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 100 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 101 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 102 | interdum massa nibh nec erat. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit 103 | a, scelerisque sed, 104 | lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque 105 | semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed 106 | posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus 107 | metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. 108 | Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget 109 | nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in 110 | interdum massa nibh nec erat. 111 |
112 | 113 | 118 | 119 | -------------------------------------------------------------------------------- /jquery.custom-scrollbar.css: -------------------------------------------------------------------------------- 1 | .scrollable { 2 | position: relative; 3 | } 4 | 5 | .scrollable:focus { 6 | outline: 0; 7 | } 8 | 9 | .scrollable .viewport { 10 | position: relative; 11 | overflow: hidden; 12 | } 13 | 14 | .scrollable .viewport .overview { 15 | position: absolute; 16 | } 17 | 18 | .scrollable .scroll-bar { 19 | display: none; 20 | } 21 | 22 | .scrollable .scroll-bar.vertical { 23 | position: absolute; 24 | right: 0; 25 | height: 100%; 26 | } 27 | 28 | .scrollable .scroll-bar.horizontal { 29 | position: relative; 30 | width: 100%; 31 | } 32 | 33 | .scrollable .scroll-bar .thumb { 34 | position: absolute; 35 | } 36 | 37 | .scrollable .scroll-bar.vertical .thumb { 38 | width: 100%; 39 | min-height: 10px; 40 | } 41 | 42 | .scrollable .scroll-bar.horizontal .thumb { 43 | height: 100%; 44 | min-width: 10px; 45 | left: 0; 46 | } 47 | 48 | .not-selectable { 49 | -webkit-touch-callout: none; 50 | -webkit-user-select: none; 51 | -khtml-user-select: none; 52 | -moz-user-select: none; 53 | -ms-user-select: none; 54 | user-select: none; 55 | } 56 | 57 | /*Default skin*/ 58 | 59 | .scrollable.default-skin { 60 | padding-right: 10px; 61 | padding-bottom: 6px; 62 | } 63 | 64 | .scrollable.default-skin .scroll-bar.vertical { 65 | width: 6px; 66 | } 67 | 68 | .scrollable.default-skin .scroll-bar.horizontal { 69 | height: 6px; 70 | } 71 | 72 | .scrollable.default-skin .scroll-bar .thumb { 73 | background-color: black; 74 | opacity: 0.4; 75 | border-radius: 3px; 76 | -moz-border-radius: 4px; 77 | -webkit-border-radius: 4px; 78 | } 79 | 80 | .scrollable.default-skin .scroll-bar:hover .thumb { 81 | opacity: 0.6; 82 | } 83 | 84 | /*Gray skin*/ 85 | 86 | .scrollable.gray-skin { 87 | padding-right: 17px; 88 | } 89 | 90 | .scrollable.gray-skin .scroll-bar { 91 | border: 1px solid gray; 92 | background-color: #d3d3d3; 93 | } 94 | 95 | .scrollable.gray-skin .scroll-bar .thumb { 96 | background-color: gray; 97 | } 98 | 99 | .scrollable.gray-skin .scroll-bar:hover .thumb { 100 | background-color: black; 101 | } 102 | 103 | .scrollable.gray-skin .scroll-bar.vertical { 104 | width: 10px; 105 | } 106 | 107 | .scrollable.gray-skin .scroll-bar.horizontal { 108 | height: 10px; 109 | margin-top: 2px; 110 | } 111 | 112 | /*Modern skin*/ 113 | .scrollable.modern-skin { 114 | padding-right: 17px; 115 | } 116 | 117 | .scrollable.modern-skin .scroll-bar { 118 | border: 1px solid gray; 119 | border-radius: 4px; 120 | -moz-border-radius: 4px; 121 | -webkit-border-radius: 4px; 122 | -moz-box-shadow: inset 0 0 5px #888; 123 | -webkit-box-shadow: inset 0 0 5px #888; 124 | box-shadow: inset 0 0 5px #888; 125 | } 126 | 127 | .scrollable.modern-skin .scroll-bar .thumb { 128 | background-color: #95aabf; 129 | border-radius: 4px; 130 | -moz-border-radius: 4px; 131 | -webkit-border-radius: 4px; 132 | border: 1px solid #536984; 133 | } 134 | 135 | .scrollable.modern-skin .scroll-bar.vertical .thumb { 136 | width: 8px; 137 | background: -moz-linear-gradient(left, #95aabf 0%, #547092 100%); 138 | background: -webkit-gradient(linear, left top, right top, color-stop(0%, #95aabf), color-stop(100%, #547092)); 139 | background: -webkit-linear-gradient(left, #95aabf 0%, #547092 100%); 140 | background: -o-linear-gradient(left, #95aabf 0%, #547092 100%); 141 | background: -ms-linear-gradient(left, #95aabf 0%, #547092 100%); 142 | background: linear-gradient(to right, #95aabf 0%, #547092 100%); 143 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#95aabf', endColorstr='#547092',GradientType=1 )"; 144 | } 145 | 146 | .scrollable.modern-skin .scroll-bar.horizontal .thumb { 147 | height: 8px; 148 | background-image: linear-gradient(#95aabf, #547092); 149 | background-image: -o-linear-gradient(#95aabf, #547092); 150 | background-image: -moz-linear-gradient(#95aabf, #547092); 151 | background-image: -webkit-linear-gradient(#95aabf, #547092); 152 | background-image: -ms-linear-gradient(#95aabf, #547092); 153 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#95aabf', endColorstr='#547092',GradientType=0 )"; 154 | } 155 | 156 | .scrollable.modern-skin .scroll-bar.vertical { 157 | width: 10px; 158 | } 159 | 160 | .scrollable.modern-skin .scroll-bar.horizontal { 161 | height: 10px; 162 | margin-top: 2px; 163 | } -------------------------------------------------------------------------------- /jquery.custom-scrollbar.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | 3 | $.fn.customScrollbar = function (options, args) { 4 | 5 | var defaultOptions = { 6 | skin: undefined, 7 | hScroll: true, 8 | vScroll: true, 9 | updateOnWindowResize: false, 10 | animationSpeed: 300, 11 | onCustomScroll: undefined, 12 | swipeSpeed: 1, 13 | wheelSpeed: 40, 14 | fixedThumbWidth: undefined, 15 | fixedThumbHeight: undefined, 16 | preventDefaultScroll: false 17 | } 18 | 19 | var Scrollable = function (element, options) { 20 | this.$element = $(element); 21 | this.options = options; 22 | this.addScrollableClass(); 23 | this.addSkinClass(); 24 | this.addScrollBarComponents(); 25 | if (this.options.vScroll) 26 | this.vScrollbar = new Scrollbar(this, new VSizing()); 27 | if (this.options.hScroll) 28 | this.hScrollbar = new Scrollbar(this, new HSizing()); 29 | this.$element.data("scrollable", this); 30 | this.initKeyboardScrolling(); 31 | this.bindEvents(); 32 | } 33 | 34 | Scrollable.prototype = { 35 | 36 | addScrollableClass: function () { 37 | if (!this.$element.hasClass("scrollable")) { 38 | this.scrollableAdded = true; 39 | this.$element.addClass("scrollable"); 40 | } 41 | }, 42 | 43 | removeScrollableClass: function () { 44 | if (this.scrollableAdded) 45 | this.$element.removeClass("scrollable"); 46 | }, 47 | 48 | addSkinClass: function () { 49 | if (typeof(this.options.skin) == "string" && !this.$element.hasClass(this.options.skin)) { 50 | this.skinClassAdded = true; 51 | this.$element.addClass(this.options.skin); 52 | } 53 | }, 54 | 55 | removeSkinClass: function () { 56 | if (this.skinClassAdded) 57 | this.$element.removeClass(this.options.skin); 58 | }, 59 | 60 | addScrollBarComponents: function () { 61 | this.assignViewPort(); 62 | if (this.$viewPort.length == 0) { 63 | this.$element.wrapInner("
"); 64 | this.assignViewPort(); 65 | this.viewPortAdded = true; 66 | } 67 | this.assignOverview(); 68 | if (this.$overview.length == 0) { 69 | this.$viewPort.wrapInner("
"); 70 | this.assignOverview(); 71 | this.overviewAdded = true; 72 | } 73 | this.addScrollBar("vertical", "prepend"); 74 | this.addScrollBar("horizontal", "append"); 75 | }, 76 | 77 | removeScrollbarComponents: function () { 78 | this.removeScrollbar("vertical"); 79 | this.removeScrollbar("horizontal"); 80 | if (this.overviewAdded) 81 | this.$element.unwrap(); 82 | if (this.viewPortAdded) 83 | this.$element.unwrap(); 84 | }, 85 | 86 | removeScrollbar: function (orientation) { 87 | if (this[orientation + "ScrollbarAdded"]) 88 | this.$element.find(".scroll-bar." + orientation).remove(); 89 | }, 90 | 91 | assignViewPort: function () { 92 | this.$viewPort = this.$element.find(".viewport"); 93 | }, 94 | 95 | assignOverview: function () { 96 | this.$overview = this.$viewPort.find(".overview"); 97 | }, 98 | 99 | addScrollBar: function (orientation, fun) { 100 | if (this.$element.find(".scroll-bar." + orientation).length == 0) { 101 | this.$element[fun]("
") 102 | this[orientation + "ScrollbarAdded"] = true; 103 | } 104 | }, 105 | 106 | resize: function (keepPosition) { 107 | if (this.vScrollbar) 108 | this.vScrollbar.resize(keepPosition); 109 | if (this.hScrollbar) 110 | this.hScrollbar.resize(keepPosition); 111 | }, 112 | 113 | scrollTo: function (element) { 114 | if (this.vScrollbar) 115 | this.vScrollbar.scrollToElement(element); 116 | if (this.hScrollbar) 117 | this.hScrollbar.scrollToElement(element); 118 | }, 119 | 120 | scrollToXY: function (x, y) { 121 | this.scrollToX(x); 122 | this.scrollToY(y); 123 | }, 124 | 125 | scrollToX: function (x) { 126 | if (this.hScrollbar) 127 | this.hScrollbar.scrollOverviewTo(x, true); 128 | }, 129 | 130 | scrollToY: function (y) { 131 | if (this.vScrollbar) 132 | this.vScrollbar.scrollOverviewTo(y, true); 133 | }, 134 | 135 | scrollByX: function (x) { 136 | if (this.hScrollbar) 137 | this.scrollToX(this.hScrollbar.overviewPosition() + x); 138 | }, 139 | 140 | scrollByY: function (y) { 141 | if (this.vScrollbar) 142 | this.scrollToY(this.vScrollbar.overviewPosition() + y); 143 | }, 144 | 145 | remove: function () { 146 | this.removeScrollableClass(); 147 | this.removeSkinClass(); 148 | this.removeScrollbarComponents(); 149 | this.$element.data("scrollable", null); 150 | this.removeKeyboardScrolling(); 151 | if (this.vScrollbar) 152 | this.vScrollbar.remove(); 153 | if (this.hScrollbar) 154 | this.hScrollbar.remove(); 155 | }, 156 | 157 | setAnimationSpeed: function (speed) { 158 | this.options.animationSpeed = speed; 159 | }, 160 | 161 | isInside: function (element, wrappingElement) { 162 | var $element = $(element); 163 | var $wrappingElement = $(wrappingElement); 164 | var elementOffset = $element.offset(); 165 | var wrappingElementOffset = $wrappingElement.offset(); 166 | return (elementOffset.top >= wrappingElementOffset.top) && (elementOffset.left >= wrappingElementOffset.left) && 167 | (elementOffset.top + $element.height() <= wrappingElementOffset.top + $wrappingElement.height()) && 168 | (elementOffset.left + $element.width() <= wrappingElementOffset.left + $wrappingElement.width()) 169 | }, 170 | 171 | initKeyboardScrolling: function () { 172 | var _this = this; 173 | 174 | this.elementKeydown = function (event) { 175 | if (document.activeElement === _this.$element[0]) { 176 | if (_this.vScrollbar) 177 | _this.vScrollbar.keyScroll(event); 178 | if (_this.hScrollbar) 179 | _this.hScrollbar.keyScroll(event); 180 | } 181 | } 182 | 183 | this.$element 184 | .attr('tabindex', '-1') 185 | .keydown(this.elementKeydown); 186 | }, 187 | 188 | removeKeyboardScrolling: function () { 189 | this.$element 190 | .removeAttr('tabindex') 191 | .unbind("keydown", this.elementKeydown); 192 | }, 193 | 194 | bindEvents: function () { 195 | if (this.options.onCustomScroll) 196 | this.$element.on("customScroll", this.options.onCustomScroll); 197 | } 198 | 199 | } 200 | 201 | var Scrollbar = function (scrollable, sizing) { 202 | this.scrollable = scrollable; 203 | this.sizing = sizing 204 | this.$scrollBar = this.sizing.scrollBar(this.scrollable.$element); 205 | this.$thumb = this.$scrollBar.find(".thumb"); 206 | this.setScrollPosition(0, 0); 207 | this.resize(); 208 | this.initMouseMoveScrolling(); 209 | this.initMouseWheelScrolling(); 210 | this.initTouchScrolling(); 211 | this.initMouseClickScrolling(); 212 | this.initWindowResize(); 213 | } 214 | 215 | Scrollbar.prototype = { 216 | 217 | resize: function (keepPosition) { 218 | this.overviewSize = this.sizing.size(this.scrollable.$overview); 219 | this.calculateViewPortSize(); 220 | this.sizing.size(this.scrollable.$viewPort, this.viewPortSize); 221 | this.ratio = this.viewPortSize / this.overviewSize; 222 | this.sizing.size(this.$scrollBar, this.viewPortSize); 223 | this.thumbSize = this.calculateThumbSize(); 224 | this.sizing.size(this.$thumb, this.thumbSize); 225 | this.maxThumbPosition = this.calculateMaxThumbPosition(); 226 | this.maxOverviewPosition = this.calculateMaxOverviewPosition(); 227 | this.enabled = (this.overviewSize > this.viewPortSize); 228 | if (this.scrollPercent === undefined) 229 | this.scrollPercent = 0.0; 230 | if (this.enabled) 231 | this.rescroll(keepPosition); 232 | else 233 | this.setScrollPosition(0, 0); 234 | this.$scrollBar.toggle(this.enabled); 235 | }, 236 | 237 | calculateViewPortSize: function () { 238 | var elementSize = this.sizing.size(this.scrollable.$element); 239 | if (elementSize > 0 && !this.maxSizeUsed) { 240 | this.viewPortSize = elementSize; 241 | this.maxSizeUsed = false; 242 | } 243 | else { 244 | var maxSize = this.sizing.maxSize(this.scrollable.$element); 245 | this.viewPortSize = Math.min(maxSize, this.overviewSize); 246 | this.maxSizeUsed = true; 247 | } 248 | }, 249 | 250 | calculateThumbSize: function () { 251 | var fixedSize = this.sizing.fixedThumbSize(this.scrollable.options) 252 | var size; 253 | if (fixedSize) 254 | size = fixedSize; 255 | else 256 | size = this.ratio * this.viewPortSize 257 | return Math.max(size, this.sizing.minSize(this.$thumb)); 258 | }, 259 | 260 | initMouseMoveScrolling: function () { 261 | var _this = this; 262 | this.$thumb.mousedown(function (event) { 263 | if (_this.enabled) 264 | _this.startMouseMoveScrolling(event); 265 | }); 266 | this.documentMouseup = function (event) { 267 | _this.stopMouseMoveScrolling(event); 268 | }; 269 | $(document).mouseup(this.documentMouseup); 270 | this.documentMousemove = function (event) { 271 | _this.mouseMoveScroll(event); 272 | }; 273 | $(document).mousemove(this.documentMousemove); 274 | this.$thumb.click(function (event) { 275 | event.stopPropagation(); 276 | }); 277 | }, 278 | 279 | removeMouseMoveScrolling: function () { 280 | this.$thumb.unbind(); 281 | $(document).unbind("mouseup", this.documentMouseup); 282 | $(document).unbind("mousemove", this.documentMousemove); 283 | }, 284 | 285 | initMouseWheelScrolling: function () { 286 | var _this = this; 287 | this.scrollable.$element.mousewheel(function (event, delta, deltaX, deltaY) { 288 | if (_this.enabled) { 289 | var scrolled = _this.mouseWheelScroll(deltaX, deltaY); 290 | _this.stopEventConditionally(event, scrolled); 291 | } 292 | }); 293 | }, 294 | 295 | removeMouseWheelScrolling: function () { 296 | this.scrollable.$element.unbind("mousewheel"); 297 | }, 298 | 299 | initTouchScrolling: function () { 300 | if (document.addEventListener) { 301 | var _this = this; 302 | this.elementTouchstart = function (event) { 303 | if (_this.enabled) 304 | _this.startTouchScrolling(event); 305 | } 306 | this.scrollable.$element[0].addEventListener("touchstart", this.elementTouchstart); 307 | this.documentTouchmove = function (event) { 308 | _this.touchScroll(event); 309 | } 310 | this.scrollable.$element[0].addEventListener("touchmove", this.documentTouchmove); 311 | this.elementTouchend = function (event) { 312 | _this.stopTouchScrolling(event); 313 | } 314 | this.scrollable.$element[0].addEventListener("touchend", this.elementTouchend); 315 | } 316 | }, 317 | 318 | removeTouchScrolling: function () { 319 | if (document.addEventListener) { 320 | this.scrollable.$element[0].removeEventListener("touchstart", this.elementTouchstart); 321 | document.removeEventListener("touchmove", this.documentTouchmove); 322 | this.scrollable.$element[0].removeEventListener("touchend", this.elementTouchend); 323 | } 324 | }, 325 | 326 | initMouseClickScrolling: function () { 327 | var _this = this; 328 | this.scrollBarClick = function (event) { 329 | _this.mouseClickScroll(event); 330 | }; 331 | this.$scrollBar.click(this.scrollBarClick); 332 | }, 333 | 334 | removeMouseClickScrolling: function () { 335 | this.$scrollBar.unbind("click", this.scrollBarClick); 336 | }, 337 | 338 | initWindowResize: function () { 339 | if (this.scrollable.options.updateOnWindowResize) { 340 | var _this = this; 341 | this.windowResize = function () { 342 | _this.resize(); 343 | }; 344 | $(window).resize(this.windowResize); 345 | } 346 | }, 347 | 348 | removeWindowResize: function () { 349 | $(window).unbind("resize", this.windowResize); 350 | }, 351 | 352 | isKeyScrolling: function (key) { 353 | return this.keyScrollDelta(key) != null; 354 | }, 355 | 356 | keyScrollDelta: function (key) { 357 | for (var scrollingKey in this.sizing.scrollingKeys) 358 | if (scrollingKey == key) 359 | return this.sizing.scrollingKeys[key](this.viewPortSize); 360 | return null; 361 | }, 362 | 363 | startMouseMoveScrolling: function (event) { 364 | this.mouseMoveScrolling = true; 365 | $("body").addClass("not-selectable"); 366 | this.setUnselectable($("body"), "on"); 367 | this.setScrollEvent(event); 368 | event.preventDefault(); 369 | }, 370 | 371 | stopMouseMoveScrolling: function (event) { 372 | this.mouseMoveScrolling = false; 373 | $("body").removeClass("not-selectable"); 374 | this.setUnselectable($("body"), null); 375 | }, 376 | 377 | setUnselectable: function (element, value) { 378 | if (element.attr("unselectable") != value) { 379 | element.attr("unselectable", value); 380 | element.find(':not(input)').attr('unselectable', value); 381 | } 382 | }, 383 | 384 | mouseMoveScroll: function (event) { 385 | if (this.mouseMoveScrolling) { 386 | var delta = this.sizing.mouseDelta(this.scrollEvent, event); 387 | this.scrollThumbBy(delta); 388 | this.setScrollEvent(event); 389 | } 390 | }, 391 | 392 | startTouchScrolling: function (event) { 393 | if (event.touches && event.touches.length == 1) { 394 | this.setScrollEvent(event.touches[0]); 395 | this.touchScrolling = true; 396 | event.stopPropagation(); 397 | } 398 | }, 399 | 400 | touchScroll: function (event) { 401 | if (this.touchScrolling && event.touches && event.touches.length == 1) { 402 | var delta = -this.sizing.mouseDelta(this.scrollEvent, event.touches[0]) * this.scrollable.options.swipeSpeed; 403 | var scrolled = this.scrollOverviewBy(delta); 404 | if (scrolled) 405 | this.setScrollEvent(event.touches[0]); 406 | this.stopEventConditionally(event, scrolled); 407 | } 408 | }, 409 | 410 | stopTouchScrolling: function (event) { 411 | this.touchScrolling = false; 412 | event.stopPropagation(); 413 | }, 414 | 415 | mouseWheelScroll: function (deltaX, deltaY) { 416 | var delta = -this.sizing.wheelDelta(deltaX, deltaY) * this.scrollable.options.wheelSpeed; 417 | if (delta != 0) 418 | return this.scrollOverviewBy(delta); 419 | }, 420 | 421 | mouseClickScroll: function (event) { 422 | var delta = this.viewPortSize - 20; 423 | if (event["page" + this.sizing.scrollAxis()] < this.$thumb.offset()[this.sizing.offsetComponent()]) 424 | // mouse click over thumb 425 | delta = -delta; 426 | this.scrollOverviewBy(delta); 427 | }, 428 | 429 | keyScroll: function (event) { 430 | var keyDown = event.which; 431 | if (this.enabled && this.isKeyScrolling(keyDown)) { 432 | var scrolled = this.scrollOverviewBy(this.keyScrollDelta(keyDown)); 433 | this.stopEventConditionally(event, scrolled); 434 | } 435 | }, 436 | 437 | scrollThumbBy: function (delta) { 438 | var thumbPosition = this.thumbPosition(); 439 | thumbPosition += delta; 440 | thumbPosition = this.positionOrMax(thumbPosition, this.maxThumbPosition); 441 | var oldScrollPercent = this.scrollPercent; 442 | this.scrollPercent = thumbPosition / this.maxThumbPosition; 443 | if (oldScrollPercent != this.scrollPercent) { 444 | var overviewPosition = (thumbPosition * this.maxOverviewPosition) / this.maxThumbPosition; 445 | this.setScrollPosition(overviewPosition, thumbPosition); 446 | this.triggerCustomScroll(oldScrollPercent); 447 | return true 448 | } 449 | else 450 | return false; 451 | }, 452 | 453 | thumbPosition: function () { 454 | return this.$thumb.position()[this.sizing.offsetComponent()]; 455 | }, 456 | 457 | scrollOverviewBy: function (delta) { 458 | var overviewPosition = this.overviewPosition() + delta; 459 | return this.scrollOverviewTo(overviewPosition, false); 460 | }, 461 | 462 | overviewPosition: function () { 463 | return -this.scrollable.$overview.position()[this.sizing.offsetComponent()]; 464 | }, 465 | 466 | scrollOverviewTo: function (overviewPosition, animate) { 467 | overviewPosition = this.positionOrMax(overviewPosition, this.maxOverviewPosition); 468 | var oldScrollPercent = this.scrollPercent; 469 | this.scrollPercent = overviewPosition / this.maxOverviewPosition; 470 | if (oldScrollPercent != this.scrollPercent) { 471 | var thumbPosition = this.scrollPercent * this.maxThumbPosition; 472 | if (animate) 473 | this.setScrollPositionWithAnimation(overviewPosition, thumbPosition); 474 | else 475 | this.setScrollPosition(overviewPosition, thumbPosition); 476 | this.triggerCustomScroll(oldScrollPercent); 477 | return true; 478 | } 479 | else 480 | return false; 481 | }, 482 | 483 | positionOrMax: function (p, max) { 484 | if (p < 0) 485 | return 0; 486 | else if (p > max) 487 | return max; 488 | else 489 | return p; 490 | }, 491 | 492 | triggerCustomScroll: function (oldScrollPercent) { 493 | this.scrollable.$element.trigger("customScroll", { 494 | scrollAxis: this.sizing.scrollAxis(), 495 | direction: this.sizing.scrollDirection(oldScrollPercent, this.scrollPercent), 496 | scrollPercent: this.scrollPercent * 100 497 | } 498 | ); 499 | }, 500 | 501 | rescroll: function (keepPosition) { 502 | if (keepPosition) { 503 | var overviewPosition = this.positionOrMax(this.overviewPosition(), this.maxOverviewPosition); 504 | this.scrollPercent = overviewPosition / this.maxOverviewPosition; 505 | var thumbPosition = this.scrollPercent * this.maxThumbPosition; 506 | this.setScrollPosition(overviewPosition, thumbPosition); 507 | } 508 | else { 509 | var thumbPosition = this.scrollPercent * this.maxThumbPosition; 510 | var overviewPosition = this.scrollPercent * this.maxOverviewPosition; 511 | this.setScrollPosition(overviewPosition, thumbPosition); 512 | } 513 | }, 514 | 515 | setScrollPosition: function (overviewPosition, thumbPosition) { 516 | this.$thumb.css(this.sizing.offsetComponent(), thumbPosition + "px"); 517 | this.scrollable.$overview.css(this.sizing.offsetComponent(), -overviewPosition + "px"); 518 | }, 519 | 520 | setScrollPositionWithAnimation: function (overviewPosition, thumbPosition) { 521 | var thumbAnimationOpts = {}; 522 | var overviewAnimationOpts = {}; 523 | thumbAnimationOpts[this.sizing.offsetComponent()] = thumbPosition + "px"; 524 | this.$thumb.animate(thumbAnimationOpts, this.scrollable.options.animationSpeed); 525 | overviewAnimationOpts[this.sizing.offsetComponent()] = -overviewPosition + "px"; 526 | this.scrollable.$overview.animate(overviewAnimationOpts, this.scrollable.options.animationSpeed); 527 | }, 528 | 529 | calculateMaxThumbPosition: function () { 530 | return Math.max(0, this.sizing.size(this.$scrollBar) - this.thumbSize); 531 | }, 532 | 533 | calculateMaxOverviewPosition: function () { 534 | return Math.max(0, this.sizing.size(this.scrollable.$overview) - this.sizing.size(this.scrollable.$viewPort)); 535 | }, 536 | 537 | setScrollEvent: function (event) { 538 | var attr = "page" + this.sizing.scrollAxis(); 539 | if (!this.scrollEvent || this.scrollEvent[attr] != event[attr]) 540 | this.scrollEvent = {pageX: event.pageX, pageY: event.pageY}; 541 | }, 542 | 543 | scrollToElement: function (element) { 544 | var $element = $(element); 545 | if (this.sizing.isInside($element, this.scrollable.$overview) && !this.sizing.isInside($element, this.scrollable.$viewPort)) { 546 | var elementOffset = $element.offset(); 547 | var overviewOffset = this.scrollable.$overview.offset(); 548 | var viewPortOffset = this.scrollable.$viewPort.offset(); 549 | this.scrollOverviewTo(elementOffset[this.sizing.offsetComponent()] - overviewOffset[this.sizing.offsetComponent()], true); 550 | } 551 | }, 552 | 553 | remove: function () { 554 | this.removeMouseMoveScrolling(); 555 | this.removeMouseWheelScrolling(); 556 | this.removeTouchScrolling(); 557 | this.removeMouseClickScrolling(); 558 | this.removeWindowResize(); 559 | }, 560 | 561 | stopEventConditionally: function (event, condition) { 562 | if (condition || this.scrollable.options.preventDefaultScroll) { 563 | event.preventDefault(); 564 | event.stopPropagation(); 565 | } 566 | } 567 | 568 | } 569 | 570 | var HSizing = function () { 571 | } 572 | 573 | HSizing.prototype = { 574 | size: function ($el, arg) { 575 | if (arg) 576 | return $el.width(arg); 577 | else 578 | return $el.width(); 579 | }, 580 | 581 | minSize: function ($el) { 582 | return parseInt($el.css("min-width")) || 0; 583 | }, 584 | 585 | maxSize: function ($el) { 586 | return parseInt($el.css("max-width")) || 0; 587 | }, 588 | 589 | fixedThumbSize: function (options) { 590 | return options.fixedThumbWidth; 591 | }, 592 | 593 | scrollBar: function ($el) { 594 | return $el.find(".scroll-bar.horizontal"); 595 | }, 596 | 597 | mouseDelta: function (event1, event2) { 598 | return event2.pageX - event1.pageX; 599 | }, 600 | 601 | offsetComponent: function () { 602 | return "left"; 603 | }, 604 | 605 | wheelDelta: function (deltaX, deltaY) { 606 | return deltaX; 607 | }, 608 | 609 | scrollAxis: function () { 610 | return "X"; 611 | }, 612 | 613 | scrollDirection: function (oldPercent, newPercent) { 614 | return oldPercent < newPercent ? "right" : "left"; 615 | }, 616 | 617 | scrollingKeys: { 618 | 37: function (viewPortSize) { 619 | return -10; //arrow left 620 | }, 621 | 39: function (viewPortSize) { 622 | return 10; //arrow right 623 | } 624 | }, 625 | 626 | isInside: function (element, wrappingElement) { 627 | var $element = $(element); 628 | var $wrappingElement = $(wrappingElement); 629 | var elementOffset = $element.offset(); 630 | var wrappingElementOffset = $wrappingElement.offset(); 631 | return (elementOffset.left >= wrappingElementOffset.left) && 632 | (elementOffset.left + $element.width() <= wrappingElementOffset.left + $wrappingElement.width()); 633 | } 634 | 635 | } 636 | 637 | var VSizing = function () { 638 | } 639 | 640 | VSizing.prototype = { 641 | 642 | size: function ($el, arg) { 643 | if (arg) 644 | return $el.height(arg); 645 | else 646 | return $el.height(); 647 | }, 648 | 649 | minSize: function ($el) { 650 | return parseInt($el.css("min-height")) || 0; 651 | }, 652 | 653 | maxSize: function ($el) { 654 | return parseInt($el.css("max-height")) || 0; 655 | }, 656 | 657 | fixedThumbSize: function (options) { 658 | return options.fixedThumbHeight; 659 | }, 660 | 661 | scrollBar: function ($el) { 662 | return $el.find(".scroll-bar.vertical"); 663 | }, 664 | 665 | mouseDelta: function (event1, event2) { 666 | return event2.pageY - event1.pageY; 667 | }, 668 | 669 | offsetComponent: function () { 670 | return "top"; 671 | }, 672 | 673 | wheelDelta: function (deltaX, deltaY) { 674 | return deltaY; 675 | }, 676 | 677 | scrollAxis: function () { 678 | return "Y"; 679 | }, 680 | 681 | scrollDirection: function (oldPercent, newPercent) { 682 | return oldPercent < newPercent ? "down" : "up"; 683 | }, 684 | 685 | scrollingKeys: { 686 | 38: function (viewPortSize) { 687 | return -10; //arrow up 688 | }, 689 | 40: function (viewPortSize) { 690 | return 10; //arrow down 691 | }, 692 | 33: function (viewPortSize) { 693 | return -(viewPortSize - 20); //page up 694 | }, 695 | 34: function (viewPortSize) { 696 | return viewPortSize - 20; //page down 697 | } 698 | }, 699 | 700 | isInside: function (element, wrappingElement) { 701 | var $element = $(element); 702 | var $wrappingElement = $(wrappingElement); 703 | var elementOffset = $element.offset(); 704 | var wrappingElementOffset = $wrappingElement.offset(); 705 | return (elementOffset.top >= wrappingElementOffset.top) && 706 | (elementOffset.top + $element.height() <= wrappingElementOffset.top + $wrappingElement.height()); 707 | } 708 | 709 | } 710 | 711 | return this.each(function () { 712 | if (options == undefined) 713 | options = defaultOptions; 714 | if (typeof(options) == "string") { 715 | var scrollable = $(this).data("scrollable"); 716 | if (scrollable) 717 | scrollable[options](args); 718 | } 719 | else if (typeof(options) == "object") { 720 | options = $.extend(defaultOptions, options); 721 | new Scrollable($(this), options); 722 | } 723 | else 724 | throw "Invalid type of options"; 725 | }); 726 | 727 | } 728 | ; 729 | 730 | }) 731 | (jQuery); 732 | 733 | (function ($) { 734 | 735 | var types = ['DOMMouseScroll', 'mousewheel']; 736 | 737 | if ($.event.fixHooks) { 738 | for (var i = types.length; i;) { 739 | $.event.fixHooks[ types[--i] ] = $.event.mouseHooks; 740 | } 741 | } 742 | 743 | $.event.special.mousewheel = { 744 | setup: function () { 745 | if (this.addEventListener) { 746 | for (var i = types.length; i;) { 747 | this.addEventListener(types[--i], handler, false); 748 | } 749 | } else { 750 | this.onmousewheel = handler; 751 | } 752 | }, 753 | 754 | teardown: function () { 755 | if (this.removeEventListener) { 756 | for (var i = types.length; i;) { 757 | this.removeEventListener(types[--i], handler, false); 758 | } 759 | } else { 760 | this.onmousewheel = null; 761 | } 762 | } 763 | }; 764 | 765 | $.fn.extend({ 766 | mousewheel: function (fn) { 767 | return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 768 | }, 769 | 770 | unmousewheel: function (fn) { 771 | return this.unbind("mousewheel", fn); 772 | } 773 | }); 774 | 775 | 776 | function handler(event) { 777 | var orgEvent = event || window.event, args = [].slice.call(arguments, 1), delta = 0, returnValue = true, deltaX = 0, deltaY = 0; 778 | event = $.event.fix(orgEvent); 779 | event.type = "mousewheel"; 780 | 781 | // Old school scrollwheel delta 782 | if (orgEvent.wheelDelta) { 783 | delta = orgEvent.wheelDelta / 120; 784 | } 785 | if (orgEvent.detail) { 786 | delta = -orgEvent.detail / 3; 787 | } 788 | 789 | // New school multidimensional scroll (touchpads) deltas 790 | deltaY = delta; 791 | 792 | // Gecko 793 | if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 794 | deltaY = 0; 795 | deltaX = delta; 796 | } 797 | 798 | // Webkit 799 | if (orgEvent.wheelDeltaY !== undefined) { 800 | deltaY = orgEvent.wheelDeltaY / 120; 801 | } 802 | if (orgEvent.wheelDeltaX !== undefined) { 803 | deltaX = orgEvent.wheelDeltaX / 120; 804 | } 805 | 806 | // Add event and delta to the front of the arguments 807 | args.unshift(event, delta, deltaX, deltaY); 808 | 809 | return ($.event.dispatch || $.event.handle).apply(this, args); 810 | } 811 | 812 | })(jQuery); 813 | --------------------------------------------------------------------------------