github.com/apremalal/vamps-core@v1.0.1-0.20161221121535-d430b56ec174/server/webapps/app/base/plugins/jquery-slimscroll/jquery.slimscroll.js (about) 1 /*! Copyright (c) 2011 Piotr Rochala (http://rocha.la) 2 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 3 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 4 * 5 * Improved by keenthemes for Metronic Theme 6 * Version: 1.3.2 7 * 8 */ 9 (function($) { 10 11 jQuery.fn.extend({ 12 slimScroll: function(options) { 13 14 var defaults = { 15 16 // width in pixels of the visible scroll area 17 width: 'auto', 18 19 // height in pixels of the visible scroll area 20 height: '250px', 21 22 // width in pixels of the scrollbar and rail 23 size: '7px', 24 25 // scrollbar color, accepts any hex/color value 26 color: '#000', 27 28 // scrollbar position - left/right 29 position: 'right', 30 31 // distance in pixels between the side edge and the scrollbar 32 distance: '1px', 33 34 // default scroll position on load - top / bottom / $('selector') 35 start: 'top', 36 37 // sets scrollbar opacity 38 opacity: .4, 39 40 // enables always-on mode for the scrollbar 41 alwaysVisible: false, 42 43 // check if we should hide the scrollbar when user is hovering over 44 disableFadeOut: false, 45 46 // sets visibility of the rail 47 railVisible: false, 48 49 // sets rail color 50 railColor: '#333', 51 52 // sets rail opacity 53 railOpacity: .2, 54 55 // whether we should use jQuery UI Draggable to enable bar dragging 56 railDraggable: true, 57 58 // defautlt CSS class of the slimscroll rail 59 railClass: 'slimScrollRail', 60 61 // defautlt CSS class of the slimscroll bar 62 barClass: 'slimScrollBar', 63 64 // defautlt CSS class of the slimscroll wrapper 65 wrapperClass: 'slimScrollDiv', 66 67 // check if mousewheel should scroll the window if we reach top/bottom 68 allowPageScroll: false, 69 70 // scroll amount applied to each mouse wheel step 71 wheelStep: 20, 72 73 // scroll amount applied when user is using gestures 74 touchScrollStep: 200, 75 76 // sets border radius 77 borderRadius: '7px', 78 79 // sets border radius of the rail 80 railBorderRadius: '7px', 81 82 // sets animation status on a given scroll(added my keenthemes) 83 animate: true 84 }; 85 86 var o = $.extend(defaults, options); 87 88 // do it for every element that matches selector 89 this.each(function() { 90 91 var isOverPanel, isOverBar, isDragg, queueHide, touchDif, 92 barHeight, percentScroll, lastScroll, 93 divS = '<div></div>', 94 minBarHeight = 30, 95 releaseScroll = false; 96 97 // used in event handlers and for better minification 98 var me = $(this); 99 100 //begin: windows phone fix added by keenthemes 101 if ('ontouchstart' in window && window.navigator.msPointerEnabled) { 102 me.css("-ms-touch-action", "none"); 103 } 104 //end: windows phone fix added by keenthemes 105 106 // ensure we are not binding it again 107 if (me.parent().hasClass(o.wrapperClass)) { 108 // start from last bar position 109 var offset = me.scrollTop(); 110 111 // find bar and rail 112 bar = me.parent().find('.' + o.barClass); 113 rail = me.parent().find('.' + o.railClass); 114 115 getBarHeight(); 116 117 // check if we should scroll existing instance 118 if ($.isPlainObject(options)) { 119 // Pass height: auto to an existing slimscroll object to force a resize after contents have changed 120 if ('height' in options && options.height == 'auto') { 121 me.parent().css('height', 'auto'); 122 me.css('height', 'auto'); 123 var height = me.parent().parent().height(); 124 me.parent().css('height', height); 125 me.css('height', height); 126 } 127 128 if ('scrollTo' in options) { 129 // jump to a static point 130 offset = parseInt(o.scrollTo); 131 } else if ('scrollBy' in options) { 132 // jump by value pixels 133 offset += parseInt(o.scrollBy); 134 } else if ('destroy' in options) { 135 // remove slimscroll elements 136 bar.remove(); 137 rail.remove(); 138 me.unwrap(); 139 return; 140 } 141 142 // scroll content by the given offset 143 scrollContent(offset, false, true); 144 } 145 146 return; 147 } 148 149 // optionally set height to the parent's height 150 o.height = (options.height == 'auto') ? me.parent().height() : options.height; 151 152 // wrap content 153 var wrapper = $(divS) 154 .addClass(o.wrapperClass) 155 .css({ 156 position: 'relative', 157 overflow: 'hidden', 158 width: o.width, 159 height: o.height 160 }); 161 162 // update style for the div 163 me.css({ 164 overflow: 'hidden', 165 width: o.width, 166 height: o.height 167 }); 168 169 // create scrollbar rail 170 var rail = $(divS) 171 .addClass(o.railClass) 172 .css({ 173 width: o.size, 174 height: '100%', 175 position: 'absolute', 176 top: 0, 177 display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none', 178 'border-radius': o.railBorderRadius, 179 background: o.railColor, 180 opacity: o.railOpacity, 181 zIndex: 90 182 }); 183 184 // create scrollbar 185 var bar = $(divS) 186 .addClass(o.barClass) 187 .css({ 188 background: o.color, 189 width: o.size, 190 position: 'absolute', 191 top: 0, 192 opacity: o.opacity, 193 display: o.alwaysVisible ? 'block' : 'none', 194 'border-radius': o.borderRadius, 195 BorderRadius: o.borderRadius, 196 MozBorderRadius: o.borderRadius, 197 WebkitBorderRadius: o.borderRadius, 198 zIndex: 99 199 }); 200 201 // set position 202 var posCss = (o.position == 'right') ? { 203 right: o.distance 204 } : { 205 left: o.distance 206 }; 207 rail.css(posCss); 208 bar.css(posCss); 209 210 // wrap it 211 me.wrap(wrapper); 212 213 // append to parent div 214 me.parent().append(bar); 215 me.parent().append(rail); 216 217 // make it draggable and no longer dependent on the jqueryUI 218 if (o.railDraggable) { 219 bar.bind("mousedown", function(e) { 220 var $doc = $(document); 221 isDragg = true; 222 t = parseFloat(bar.css('top')); 223 pageY = e.pageY; 224 225 $doc.bind("mousemove.slimscroll", function(e) { 226 currTop = t + e.pageY - pageY; 227 bar.css('top', currTop); 228 scrollContent(0, bar.position().top, false); // scroll content 229 }); 230 231 $doc.bind("mouseup.slimscroll", function(e) { 232 isDragg = false; 233 hideBar(); 234 $doc.unbind('.slimscroll'); 235 }); 236 return false; 237 }).bind("selectstart.slimscroll", function(e) { 238 e.stopPropagation(); 239 e.preventDefault(); 240 return false; 241 }); 242 } 243 244 //begin: windows phone fix added by keenthemes 245 if ('ontouchstart' in window && window.navigator.msPointerEnabled) { 246 me.bind('MSPointerDown', function(e, b) { 247 // record where touch started 248 touchDif = e.originalEvent.pageY; 249 }); 250 251 me.bind('MSPointerMove', function(e) { 252 // prevent scrolling the page if necessary 253 e.originalEvent.preventDefault(); 254 // see how far user swiped 255 var diff = (touchDif - e.originalEvent.pageY) / o.touchScrollStep; 256 // scroll content 257 scrollContent(diff, true); 258 touchDif = e.originalEvent.pageY; 259 }); 260 } 261 //end: windows phone fix added by keenthemes 262 263 // on rail over 264 rail.hover(function() { 265 showBar(); 266 }, function() { 267 hideBar(); 268 }); 269 270 // on bar over 271 bar.hover(function() { 272 isOverBar = true; 273 }, function() { 274 isOverBar = false; 275 }); 276 277 // show on parent mouseover 278 me.hover(function() { 279 isOverPanel = true; 280 showBar(); 281 hideBar(); 282 }, function() { 283 isOverPanel = false; 284 hideBar(); 285 }); 286 287 // support for mobile 288 me.bind('touchstart', function(e, b) { 289 if (e.originalEvent.touches.length) { 290 // record where touch started 291 touchDif = e.originalEvent.touches[0].pageY; 292 } 293 }); 294 295 me.bind('touchmove', function(e) { 296 // prevent scrolling the page if necessary 297 if (!releaseScroll) { 298 e.originalEvent.preventDefault(); 299 } 300 if (e.originalEvent.touches.length) { 301 // see how far user swiped 302 var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep; 303 // scroll content 304 scrollContent(diff, true); 305 touchDif = e.originalEvent.touches[0].pageY; 306 } 307 }); 308 309 // set up initial height 310 getBarHeight(); 311 312 // check start position 313 if (o.start === 'bottom') { 314 // scroll content to bottom 315 bar.css({ 316 top: me.outerHeight() - bar.outerHeight() 317 }); 318 scrollContent(0, true); 319 } else if (o.start !== 'top') { 320 // assume jQuery selector 321 scrollContent($(o.start).position().top, null, true); 322 323 // make sure bar stays hidden 324 if (!o.alwaysVisible) { 325 bar.hide(); 326 } 327 } 328 329 // attach scroll events 330 attachWheel(); 331 332 function _onWheel(e) { 333 // use mouse wheel only when mouse is over 334 if (!isOverPanel) { 335 return; 336 } 337 338 var e = e || window.event; 339 340 var delta = 0; 341 if (e.wheelDelta) { 342 delta = -e.wheelDelta / 120; 343 } 344 if (e.detail) { 345 delta = e.detail / 3; 346 } 347 348 var target = e.target || e.srcTarget || e.srcElement; 349 if ($(target).closest('.' + o.wrapperClass).is(me.parent())) { 350 // scroll content 351 scrollContent(delta, true); 352 } 353 354 // stop window scroll 355 if (e.preventDefault && !releaseScroll) { 356 e.preventDefault(); 357 } 358 if (!releaseScroll) { 359 e.returnValue = false; 360 } 361 } 362 363 function scrollContent(y, isWheel, isJump) { 364 releaseScroll = false; 365 var delta = y; 366 var maxTop = me.outerHeight() - bar.outerHeight(); 367 368 if (isWheel) { 369 // move bar with mouse wheel 370 delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight(); 371 372 // move bar, make sure it doesn't go out 373 delta = Math.min(Math.max(delta, 0), maxTop); 374 375 // if scrolling down, make sure a fractional change to the 376 // scroll position isn't rounded away when the scrollbar's CSS is set 377 // this flooring of delta would happened automatically when 378 // bar.css is set below, but we floor here for clarity 379 delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta); 380 381 // scroll the scrollbar 382 bar.css({ 383 top: delta + 'px' 384 }); 385 } 386 387 // calculate actual scroll amount 388 percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight()); 389 delta = percentScroll * (me[0].scrollHeight - me.outerHeight()); 390 391 if (isJump) { 392 delta = y; 393 var offsetTop = delta / me[0].scrollHeight * me.outerHeight(); 394 offsetTop = Math.min(Math.max(offsetTop, 0), maxTop); 395 bar.css({ 396 top: offsetTop + 'px' 397 }); 398 } 399 400 // scroll content 401 if ('scrollTo' in o && o.animate) { 402 me.animate({ 403 scrollTop: delta 404 }); 405 } else { 406 me.scrollTop(delta); 407 } 408 409 // fire scrolling event 410 me.trigger('slimscrolling', ~~delta); 411 412 // ensure bar is visible 413 showBar(); 414 415 // trigger hide when scroll is stopped 416 hideBar(); 417 418 } 419 420 function attachWheel() { 421 if (window.addEventListener) { 422 this.addEventListener('DOMMouseScroll', _onWheel, false); 423 this.addEventListener('mousewheel', _onWheel, false); 424 } else { 425 document.attachEvent("onmousewheel", _onWheel) 426 } 427 } 428 429 function getBarHeight() { 430 // calculate scrollbar height and make sure it is not too small 431 barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight); 432 bar.css({ 433 height: barHeight + 'px' 434 }); 435 436 // hide scrollbar if content is not long enough 437 var display = barHeight == me.outerHeight() ? 'none' : 'block'; 438 bar.css({ 439 display: display 440 }); 441 } 442 443 function showBar() { 444 // recalculate bar height 445 getBarHeight(); 446 clearTimeout(queueHide); 447 448 // when bar reached top or bottom 449 if (percentScroll == ~~percentScroll) { 450 //release wheel 451 releaseScroll = o.allowPageScroll; 452 453 // publish approporiate event 454 if (lastScroll != percentScroll) { 455 var msg = (~~percentScroll == 0) ? 'top' : 'bottom'; 456 me.trigger('slimscroll', msg); 457 } 458 } else { 459 releaseScroll = false; 460 } 461 lastScroll = percentScroll; 462 463 // show only when required 464 if (barHeight >= me.outerHeight()) { 465 //allow window scroll 466 releaseScroll = true; 467 return; 468 } 469 bar.stop(true, true).fadeIn('fast'); 470 if (o.railVisible) { 471 rail.stop(true, true).fadeIn('fast'); 472 } 473 } 474 475 function hideBar() { 476 // only hide when options allow it 477 if (!o.alwaysVisible) { 478 queueHide = setTimeout(function() { 479 if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg) { 480 bar.fadeOut('slow'); 481 rail.fadeOut('slow'); 482 } 483 }, 1000); 484 } 485 } 486 487 }); 488 489 // maintain chainability 490 return this; 491 } 492 }); 493 494 jQuery.fn.extend({ 495 slimscroll: jQuery.fn.slimScroll 496 }); 497 498 })(jQuery);