PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.1.7.3
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.1.7.3
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / assets / src / js / vendor / jquery / jquery.scrollbar.js

jquery.scrollbar.js in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.1.7.3, at assets/src/js/vendor/jquery/jquery.scrollbar.js

781 lines 31.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * jQuery CSS Customizable Scrollbar
3 *
4 * Copyright 2015, Yuriy Khabarov
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 *
7 * If you found bug, please contact me via email <13real008@gmail.com>
8 *
9 * @author Yuriy Khabarov aka Gromo
10 * @version 0.2.10
11 * @url https://github.com/gromo/jquery.scrollbar/
12 *
13 */
14 ;
15 (function (root, factory) {
16 if (typeof define === 'function' && define.amd) {
17 define(['jquery'], factory);
18 } else {
19 factory(root.jQuery);
20 }
21 }(this, function ($) {
22 'use strict';
23 // init flags & variables
24 var debug = false;
25
26 var browser = {
27 data: {
28 index: 0,
29 name: 'scrollbar'
30 },
31 macosx: /mac/i.test(navigator.platform),
32 mobile: /android|webos|iphone|ipad|ipod|blackberry/i.test(navigator.userAgent),
33 overlay: null,
34 scroll: null,
35 scrolls: [],
36 webkit: /webkit/i.test(navigator.userAgent) && !/edge\/\d+/i.test(navigator.userAgent)
37 };
38
39 browser.scrolls.add = function (instance) {
40 this.remove(instance).push(instance);
41 };
42 browser.scrolls.remove = function (instance) {
43 while ($.inArray(instance, this) >= 0) {
44 this.splice($.inArray(instance, this), 1);
45 }
46 return this;
47 };
48
49 var defaults = {
50 "autoScrollSize": true, // automatically calculate scrollsize
51 "autoUpdate": true, // update scrollbar if content/container size changed
52 "debug": false, // debug mode
53 "disableBodyScroll": false, // disable body scroll if mouse over container
54 "duration": 200, // scroll animate duration in ms
55 "ignoreMobile": false, // ignore mobile devices
56 "ignoreOverlay": false, // ignore browsers with overlay scrollbars (mobile, MacOS)
57 "scrollStep": 30, // scroll step for scrollbar arrows
58 "showArrows": false, // add class to show arrows
59 "stepScrolling": true, // when scrolling to scrollbar mousedown position
60
61 "scrollx": null, // horizontal scroll element
62 "scrolly": null, // vertical scroll element
63
64 "onDestroy": null, // callback function on destroy,
65 "onInit": null, // callback function on first initialization
66 "onScroll": null, // callback function on content scrolling
67 "onUpdate": null // callback function on init/resize (before scrollbar size calculation)
68 };
69
70
71 var BaseScrollbar = function (container) {
72
73 if (!browser.scroll) {
74 browser.overlay = isScrollOverlaysContent();
75 browser.scroll = getBrowserScrollSize();
76 updateScrollbars();
77
78 $(window).resize(function () {
79 var forceUpdate = false;
80 if (browser.scroll && (browser.scroll.height || browser.scroll.width)) {
81 var scroll = getBrowserScrollSize();
82 if (scroll.height !== browser.scroll.height || scroll.width !== browser.scroll.width) {
83 browser.scroll = scroll;
84 forceUpdate = true; // handle page zoom
85 }
86 }
87 updateScrollbars(forceUpdate);
88 });
89 }
90
91 this.container = container;
92 this.namespace = '.scrollbar_' + browser.data.index++;
93 this.options = $.extend({}, defaults, window.jQueryScrollbarOptions || {});
94 this.scrollTo = null;
95 this.scrollx = {};
96 this.scrolly = {};
97
98 container.data(browser.data.name, this);
99 browser.scrolls.add(this);
100 };
101
102 BaseScrollbar.prototype = {
103
104 destroy: function () {
105
106 if (!this.wrapper) {
107 return;
108 }
109
110 this.container.removeData(browser.data.name);
111 browser.scrolls.remove(this);
112
113 // init variables
114 var scrollLeft = this.container.scrollLeft();
115 var scrollTop = this.container.scrollTop();
116
117 this.container.insertBefore(this.wrapper).css({
118 "height": "",
119 "margin": "",
120 "max-height": ""
121 })
122 .removeClass('scroll-content scroll-scrollx_visible scroll-scrolly_visible')
123 .off(this.namespace)
124 .scrollLeft(scrollLeft)
125 .scrollTop(scrollTop);
126
127 this.scrollx.scroll.removeClass('scroll-scrollx_visible').find('div').andSelf().off(this.namespace);
128 this.scrolly.scroll.removeClass('scroll-scrolly_visible').find('div').andSelf().off(this.namespace);
129
130 this.wrapper.remove();
131
132 $(document).add('body').off(this.namespace);
133
134 if ($.isFunction(this.options.onDestroy)){
135 this.options.onDestroy.apply(this, [this.container]);
136 }
137 },
138 init: function (options) {
139 // init variables
140 var S = this,
141 c = this.container,
142 cw = this.containerWrapper || c,
143 namespace = this.namespace,
144 o = $.extend(this.options, options || {}),
145 s = {x: this.scrollx, y: this.scrolly},
146 w = this.wrapper;
147
148 var initScroll = {
149 "scrollLeft": c.scrollLeft(),
150 "scrollTop": c.scrollTop()
151 };
152
153 // do not init if in ignorable browser
154 if ((browser.mobile && o.ignoreMobile)
155 || (browser.overlay && o.ignoreOverlay)
156 || (browser.macosx && !browser.webkit) // still required to ignore nonWebKit browsers on Mac
157 ) {
158 //return false;
159 }
160
161 // init scroll container
162 if (!w) {
163 this.wrapper = w = $('<div>').addClass('scroll-wrapper').addClass(c.attr('class'))
164 .css('position', c.css('position') == 'absolute' ? 'absolute' : 'relative')
165 .insertBefore(c).append(c);
166
167 if (c.is('textarea')) {
168 this.containerWrapper = cw = $('<div>').insertBefore(c).append(c);
169 w.addClass('scroll-textarea');
170 }
171
172 cw.addClass('scroll-content').css({
173 "height": "auto",
174 "margin-bottom": browser.scroll.height * -1 + 'px',
175 "margin-right": browser.scroll.width * -1 + 'px',
176 "max-height": ""
177 });
178
179 c.on('scroll' + namespace, function (event) {
180 if ($.isFunction(o.onScroll)) {
181 o.onScroll.call(S, {
182 "maxScroll": s.y.maxScrollOffset,
183 "scroll": c.scrollTop(),
184 "size": s.y.size,
185 "visible": s.y.visible
186 }, {
187 "maxScroll": s.x.maxScrollOffset,
188 "scroll": c.scrollLeft(),
189 "size": s.x.size,
190 "visible": s.x.visible
191 });
192 }
193 s.x.isVisible && s.x.scroll.bar.css('left', c.scrollLeft() * s.x.kx + 'px');
194 s.y.isVisible && s.y.scroll.bar.css('top', c.scrollTop() * s.y.kx + 'px');
195 });
196
197 /* prevent native scrollbars to be visible on #anchor click */
198 w.on('scroll' + namespace, function () {
199 w.scrollTop(0).scrollLeft(0);
200 });
201
202 if (o.disableBodyScroll) {
203 var handleMouseScroll = function (event) {
204 isVerticalScroll(event) ?
205 s.y.isVisible && s.y.mousewheel(event) :
206 s.x.isVisible && s.x.mousewheel(event);
207 };
208 w.on('MozMousePixelScroll' + namespace, handleMouseScroll);
209 w.on('mousewheel' + namespace, handleMouseScroll);
210
211 if (browser.mobile) {
212 w.on('touchstart' + namespace, function (event) {
213 var touch = event.originalEvent.touches && event.originalEvent.touches[0] || event;
214 var originalTouch = {
215 "pageX": touch.pageX,
216 "pageY": touch.pageY
217 };
218 var originalScroll = {
219 "left": c.scrollLeft(),
220 "top": c.scrollTop()
221 };
222 $(document).on('touchmove' + namespace, function (event) {
223 var touch = event.originalEvent.targetTouches && event.originalEvent.targetTouches[0] || event;
224 c.scrollLeft(originalScroll.left + originalTouch.pageX - touch.pageX);
225 c.scrollTop(originalScroll.top + originalTouch.pageY - touch.pageY);
226 event.preventDefault();
227 });
228 $(document).on('touchend' + namespace, function () {
229 $(document).off(namespace);
230 });
231 });
232 }
233 }
234 if ($.isFunction(o.onInit)){
235 o.onInit.apply(this, [c]);
236 }
237
238 } else {
239 cw.css({
240 "height": "auto",
241 "margin-bottom": browser.scroll.height * -1 + 'px',
242 "margin-right": browser.scroll.width * -1 + 'px',
243 "max-height": ""
244 });
245 }
246
247 // init scrollbars & recalculate sizes
248 $.each(s, function (d, scrollx) {
249
250 var scrollCallback = null;
251 var scrollForward = 1;
252 var scrollOffset = (d === 'x') ? 'scrollLeft' : 'scrollTop';
253 var scrollStep = o.scrollStep;
254 var scrollTo = function () {
255 var currentOffset = c[scrollOffset]();
256 c[scrollOffset](currentOffset + scrollStep);
257 if (scrollForward == 1 && (currentOffset + scrollStep) >= scrollToValue)
258 currentOffset = c[scrollOffset]();
259 if (scrollForward == -1 && (currentOffset + scrollStep) <= scrollToValue)
260 currentOffset = c[scrollOffset]();
261 if (c[scrollOffset]() == currentOffset && scrollCallback) {
262 scrollCallback();
263 }
264 }
265 var scrollToValue = 0;
266
267 if (!scrollx.scroll) {
268
269 scrollx.scroll = S._getScroll(o['scroll' + d]).addClass('scroll-' + d);
270
271 if(o.showArrows){
272 scrollx.scroll.addClass('scroll-element_arrows_visible');
273 }
274
275 scrollx.mousewheel = function (event) {
276
277 if (!scrollx.isVisible || (d === 'x' && isVerticalScroll(event))) {
278 return true;
279 }
280 if (d === 'y' && !isVerticalScroll(event)) {
281 s.x.mousewheel(event);
282 return true;
283 }
284
285 var delta = event.originalEvent.wheelDelta * -1 || event.originalEvent.detail;
286 var maxScrollValue = scrollx.size - scrollx.visible - scrollx.offset;
287
288 if ((delta > 0 && scrollToValue < maxScrollValue) || (delta < 0 && scrollToValue > 0)) {
289 scrollToValue = scrollToValue + delta;
290 if (scrollToValue < 0)
291 scrollToValue = 0;
292 if (scrollToValue > maxScrollValue)
293 scrollToValue = maxScrollValue;
294
295 S.scrollTo = S.scrollTo || {};
296 S.scrollTo[scrollOffset] = scrollToValue;
297 setTimeout(function () {
298 if (S.scrollTo) {
299 c.stop().animate(S.scrollTo, 240, 'linear', function () {
300 scrollToValue = c[scrollOffset]();
301 });
302 S.scrollTo = null;
303 }
304 }, 1);
305 }
306
307 event.preventDefault();
308 return false;
309 };
310
311 scrollx.scroll
312 .on('MozMousePixelScroll' + namespace, scrollx.mousewheel)
313 .on('mousewheel' + namespace, scrollx.mousewheel)
314 .on('mouseenter' + namespace, function () {
315 scrollToValue = c[scrollOffset]();
316 });
317
318 // handle arrows & scroll inner mousedown event
319 scrollx.scroll.find('.scroll-arrow, .scroll-element_track')
320 .on('mousedown' + namespace, function (event) {
321
322 if (event.which != 1) // lmb
323 return true;
324
325 scrollForward = 1;
326
327 var data = {
328 "eventOffset": event[(d === 'x') ? 'pageX' : 'pageY'],
329 "maxScrollValue": scrollx.size - scrollx.visible - scrollx.offset,
330 "scrollbarOffset": scrollx.scroll.bar.offset()[(d === 'x') ? 'left' : 'top'],
331 "scrollbarSize": scrollx.scroll.bar[(d === 'x') ? 'outerWidth' : 'outerHeight']()
332 };
333 var timeout = 0, timer = 0;
334
335 if ($(this).hasClass('scroll-arrow')) {
336 scrollForward = $(this).hasClass("scroll-arrow_more") ? 1 : -1;
337 scrollStep = o.scrollStep * scrollForward;
338 scrollToValue = scrollForward > 0 ? data.maxScrollValue : 0;
339 } else {
340 scrollForward = (data.eventOffset > (data.scrollbarOffset + data.scrollbarSize) ? 1
341 : (data.eventOffset < data.scrollbarOffset ? -1 : 0));
342 scrollStep = Math.round(scrollx.visible * 0.75) * scrollForward;
343 scrollToValue = (data.eventOffset - data.scrollbarOffset -
344 (o.stepScrolling ? (scrollForward == 1 ? data.scrollbarSize : 0)
345 : Math.round(data.scrollbarSize / 2)));
346 scrollToValue = c[scrollOffset]() + (scrollToValue / scrollx.kx);
347 }
348
349 S.scrollTo = S.scrollTo || {};
350 S.scrollTo[scrollOffset] = o.stepScrolling ? c[scrollOffset]() + scrollStep : scrollToValue;
351
352 if (o.stepScrolling) {
353 scrollCallback = function () {
354 scrollToValue = c[scrollOffset]();
355 clearInterval(timer);
356 clearTimeout(timeout);
357 timeout = 0;
358 timer = 0;
359 };
360 timeout = setTimeout(function () {
361 timer = setInterval(scrollTo, 40);
362 }, o.duration + 100);
363 }
364
365 setTimeout(function () {
366 if (S.scrollTo) {
367 c.animate(S.scrollTo, o.duration);
368 S.scrollTo = null;
369 }
370 }, 1);
371
372 return S._handleMouseDown(scrollCallback, event);
373 });
374
375 // handle scrollbar drag'n'drop
376 scrollx.scroll.bar.on('mousedown' + namespace, function (event) {
377
378 if (event.which != 1) // lmb
379 return true;
380
381 var eventPosition = event[(d === 'x') ? 'pageX' : 'pageY'];
382 var initOffset = c[scrollOffset]();
383
384 scrollx.scroll.addClass('scroll-draggable');
385
386 $(document).on('mousemove' + namespace, function (event) {
387 var diff = parseInt((event[(d === 'x') ? 'pageX' : 'pageY'] - eventPosition) / scrollx.kx, 10);
388 c[scrollOffset](initOffset + diff);
389 });
390
391 return S._handleMouseDown(function () {
392 scrollx.scroll.removeClass('scroll-draggable');
393 scrollToValue = c[scrollOffset]();
394 }, event);
395 });
396 }
397 });
398
399 // remove classes & reset applied styles
400 $.each(s, function (d, scrollx) {
401 var scrollClass = 'scroll-scroll' + d + '_visible';
402 var scrolly = (d == "x") ? s.y : s.x;
403
404 scrollx.scroll.removeClass(scrollClass);
405 scrolly.scroll.removeClass(scrollClass);
406 cw.removeClass(scrollClass);
407 });
408
409 // calculate init sizes
410 $.each(s, function (d, scrollx) {
411 $.extend(scrollx, (d == "x") ? {
412 "offset": parseInt(c.css('left'), 10) || 0,
413 "size": c.prop('scrollWidth'),
414 "visible": w.width()
415 } : {
416 "offset": parseInt(c.css('top'), 10) || 0,
417 "size": c.prop('scrollHeight'),
418 "visible": w.height()
419 });
420 });
421
422 // update scrollbar visibility/dimensions
423 this._updateScroll('x', this.scrollx);
424 this._updateScroll('y', this.scrolly);
425
426 if ($.isFunction(o.onUpdate)){
427 o.onUpdate.apply(this, [c]);
428 }
429
430 // calculate scroll size
431 $.each(s, function (d, scrollx) {
432
433 var cssOffset = (d === 'x') ? 'left' : 'top';
434 var cssFullSize = (d === 'x') ? 'outerWidth' : 'outerHeight';
435 var cssSize = (d === 'x') ? 'width' : 'height';
436 var offset = parseInt(c.css(cssOffset), 10) || 0;
437
438 var AreaSize = scrollx.size;
439 var AreaVisible = scrollx.visible + offset;
440
441 var scrollSize = scrollx.scroll.size[cssFullSize]() + (parseInt(scrollx.scroll.size.css(cssOffset), 10) || 0);
442
443 if (o.autoScrollSize) {
444 scrollx.scrollbarSize = parseInt(scrollSize * AreaVisible / AreaSize, 10);
445 scrollx.scroll.bar.css(cssSize, scrollx.scrollbarSize + 'px');
446 }
447
448 scrollx.scrollbarSize = scrollx.scroll.bar[cssFullSize]();
449 scrollx.kx = ((scrollSize - scrollx.scrollbarSize) / (AreaSize - AreaVisible)) || 1;
450 scrollx.maxScrollOffset = AreaSize - AreaVisible;
451 });
452
453 c.scrollLeft(initScroll.scrollLeft).scrollTop(initScroll.scrollTop).trigger('scroll');
454 },
455
456 /**
457 * Get scrollx/scrolly object
458 *
459 * @param {Mixed} scroll
460 * @returns {jQuery} scroll object
461 */
462 _getScroll: function (scroll) {
463 var types = {
464 advanced: [
465 '<div class="scroll-element">',
466 '<div class="scroll-element_corner"></div>',
467 '<div class="scroll-arrow scroll-arrow_less"></div>',
468 '<div class="scroll-arrow scroll-arrow_more"></div>',
469 '<div class="scroll-element_outer">',
470 '<div class="scroll-element_size"></div>', // required! used for scrollbar size calculation !
471 '<div class="scroll-element_inner-wrapper">',
472 '<div class="scroll-element_inner scroll-element_track">', // used for handling scrollbar click
473 '<div class="scroll-element_inner-bottom"></div>',
474 '</div>',
475 '</div>',
476 '<div class="scroll-bar">', // required
477 '<div class="scroll-bar_body">',
478 '<div class="scroll-bar_body-inner"></div>',
479 '</div>',
480 '<div class="scroll-bar_bottom"></div>',
481 '<div class="scroll-bar_center"></div>',
482 '</div>',
483 '</div>',
484 '</div>'
485 ].join(''),
486 simple: [
487 '<div class="scroll-element">',
488 '<div class="scroll-element_outer">',
489 '<div class="scroll-element_size"></div>', // required! used for scrollbar size calculation !
490 '<div class="scroll-element_track"></div>', // used for handling scrollbar click
491 '<div class="scroll-bar"></div>', // required
492 '</div>',
493 '</div>'
494 ].join('')
495 };
496 if (types[scroll]) {
497 scroll = types[scroll];
498 }
499 if (!scroll) {
500 scroll = types['simple'];
501 }
502 if (typeof (scroll) == 'string') {
503 scroll = $(scroll).appendTo(this.wrapper);
504 } else {
505 scroll = $(scroll);
506 }
507 $.extend(scroll, {
508 bar: scroll.find('.scroll-bar'),
509 size: scroll.find('.scroll-element_size'),
510 track: scroll.find('.scroll-element_track')
511 });
512 return scroll;
513 },
514
515 _handleMouseDown: function(callback, event) {
516
517 var namespace = this.namespace;
518
519 $(document).on('blur' + namespace, function () {
520 $(document).add('body').off(namespace);
521 callback && callback();
522 });
523 $(document).on('dragstart' + namespace, function (event) {
524 event.preventDefault();
525 return false;
526 });
527 $(document).on('mouseup' + namespace, function () {
528 $(document).add('body').off(namespace);
529 callback && callback();
530 });
531 $('body').on('selectstart' + namespace, function (event) {
532 event.preventDefault();
533 return false;
534 });
535
536 event && event.preventDefault();
537 return false;
538 },
539
540 _updateScroll: function (d, scrollx) {
541
542 var container = this.container,
543 containerWrapper = this.containerWrapper || container,
544 scrollClass = 'scroll-scroll' + d + '_visible',
545 scrolly = (d === 'x') ? this.scrolly : this.scrollx,
546 offset = parseInt(this.container.css((d === 'x') ? 'left' : 'top'), 10) || 0,
547 wrapper = this.wrapper;
548
549 var AreaSize = scrollx.size;
550 var AreaVisible = scrollx.visible + offset;
551
552 scrollx.isVisible = (AreaSize - AreaVisible) > 1; // bug in IE9/11 with 1px diff
553 if (scrollx.isVisible) {
554 scrollx.scroll.addClass(scrollClass);
555 scrolly.scroll.addClass(scrollClass);
556 containerWrapper.addClass(scrollClass);
557 } else {
558 scrollx.scroll.removeClass(scrollClass);
559 scrolly.scroll.removeClass(scrollClass);
560 containerWrapper.removeClass(scrollClass);
561 }
562
563 if (d === 'y') {
564 if(container.is('textarea') || AreaSize < AreaVisible){
565 containerWrapper.css({
566 "height": (AreaVisible + browser.scroll.height) + 'px',
567 "max-height": "none"
568 });
569 } else {
570 containerWrapper.css({
571 //"height": "auto", // do not reset height value: issue with height:100%!
572 "max-height": (AreaVisible + browser.scroll.height) + 'px'
573 });
574 }
575 }
576
577 if (scrollx.size != container.prop('scrollWidth')
578 || scrolly.size != container.prop('scrollHeight')
579 || scrollx.visible != wrapper.width()
580 || scrolly.visible != wrapper.height()
581 || scrollx.offset != (parseInt(container.css('left'), 10) || 0)
582 || scrolly.offset != (parseInt(container.css('top'), 10) || 0)
583 ) {
584 $.extend(this.scrollx, {
585 "offset": parseInt(container.css('left'), 10) || 0,
586 "size": container.prop('scrollWidth'),
587 "visible": wrapper.width()
588 });
589 $.extend(this.scrolly, {
590 "offset": parseInt(container.css('top'), 10) || 0,
591 "size": this.container.prop('scrollHeight'),
592 "visible": wrapper.height()
593 });
594 this._updateScroll(d === 'x' ? 'y' : 'x', scrolly);
595 }
596 }
597 };
598
599 var CustomScrollbar = BaseScrollbar;
600
601 /*
602 * Extend jQuery as plugin
603 *
604 * @param {Mixed} command to execute
605 * @param {Mixed} arguments as Array
606 * @return {jQuery}
607 */
608 $.fn.scrollbar = function (command, args) {
609 if (typeof command !== 'string') {
610 args = command;
611 command = 'init';
612 }
613 if (typeof args === 'undefined') {
614 args = [];
615 }
616 if (!$.isArray(args)) {
617 args = [args];
618 }
619 this.not('body, .scroll-wrapper').each(function () {
620 var element = $(this),
621 instance = element.data(browser.data.name);
622 if (instance || command === 'init') {
623 if (!instance) {
624 instance = new CustomScrollbar(element);
625 }
626 if (instance[command]) {
627 instance[command].apply(instance, args);
628 }
629 }
630 });
631 return this;
632 };
633
634 /**
635 * Connect default options to global object
636 */
637 $.fn.scrollbar.options = defaults;
638
639
640 /**
641 * Check if scroll content/container size is changed
642 */
643
644 var updateScrollbars = (function () {
645 var timer = 0,
646 timerCounter = 0;
647
648 return function (force) {
649 var i, container, options, scroll, wrapper, scrollx, scrolly;
650 for (i = 0; i < browser.scrolls.length; i++) {
651 scroll = browser.scrolls[i];
652 container = scroll.container;
653 options = scroll.options;
654 wrapper = scroll.wrapper;
655 scrollx = scroll.scrollx;
656 scrolly = scroll.scrolly;
657 if (force || (options.autoUpdate && wrapper && wrapper.is(':visible') &&
658 (container.prop('scrollWidth') != scrollx.size || container.prop('scrollHeight') != scrolly.size || wrapper.width() != scrollx.visible || wrapper.height() != scrolly.visible))) {
659 scroll.init();
660
661 if (options.debug) {
662 window.console && console.log({
663 scrollHeight: container.prop('scrollHeight') + ':' + scroll.scrolly.size,
664 scrollWidth: container.prop('scrollWidth') + ':' + scroll.scrollx.size,
665 visibleHeight: wrapper.height() + ':' + scroll.scrolly.visible,
666 visibleWidth: wrapper.width() + ':' + scroll.scrollx.visible
667 }, true);
668 timerCounter++;
669 }
670 }
671 }
672 if (debug && timerCounter > 10) {
673 window.console && console.log('Scroll updates exceed 10');
674 updateScrollbars = function () {};
675 } else {
676 clearTimeout(timer);
677 timer = setTimeout(updateScrollbars, 300);
678 }
679 };
680 })();
681
682 /* ADDITIONAL FUNCTIONS */
683 /**
684 * Get native browser scrollbar size (height/width)
685 *
686 * @param {Boolean} actual size or CSS size, default - CSS size
687 * @returns {Object} with height, width
688 */
689 function getBrowserScrollSize(actualSize) {
690
691 if (browser.webkit && !actualSize) {
692 return {
693 "height": 0,
694 "width": 0
695 };
696 }
697
698 if (!browser.data.outer) {
699 var css = {
700 "border": "none",
701 "box-sizing": "content-box",
702 "height": "200px",
703 "margin": "0",
704 "padding": "0",
705 "width": "200px"
706 };
707 browser.data.inner = $("<div>").css($.extend({}, css));
708 browser.data.outer = $("<div>").css($.extend({
709 "left": "-1000px",
710 "overflow": "scroll",
711 "position": "absolute",
712 "top": "-1000px"
713 }, css)).append(browser.data.inner).appendTo("body");
714 }
715
716 browser.data.outer.scrollLeft(1000).scrollTop(1000);
717
718 return {
719 "height": Math.ceil((browser.data.outer.offset().top - browser.data.inner.offset().top) || 0),
720 "width": Math.ceil((browser.data.outer.offset().left - browser.data.inner.offset().left) || 0)
721 };
722 }
723
724 /**
725 * Check if native browser scrollbars overlay content
726 *
727 * @returns {Boolean}
728 */
729 function isScrollOverlaysContent() {
730 var scrollSize = getBrowserScrollSize(true);
731 return !(scrollSize.height || scrollSize.width);
732 }
733
734 function isVerticalScroll(event) {
735 var e = event.originalEvent;
736 if (e.axis && e.axis === e.HORIZONTAL_AXIS)
737 return false;
738 if (e.wheelDeltaX)
739 return false;
740 return true;
741 }
742
743
744 /**
745 * Extend AngularJS as UI directive
746 * and expose a provider for override default config
747 *
748 */
749 if (window.angular) {
750 (function (angular) {
751 angular.module('jQueryScrollbar', [])
752 .provider('jQueryScrollbar', function () {
753 var defaultOptions = defaults;
754 return {
755 setOptions: function (options) {
756 angular.extend(defaultOptions, options);
757 },
758 $get: function () {
759 return {
760 options: angular.copy(defaultOptions)
761 };
762 }
763 };
764 })
765 .directive('jqueryScrollbar', ['jQueryScrollbar', '$parse', function (jQueryScrollbar, $parse) {
766 return {
767 "restrict": "AC",
768 "link": function (scope, element, attrs) {
769 var model = $parse(attrs.jqueryScrollbar),
770 options = model(scope);
771 element.scrollbar(options || jQueryScrollbar.options)
772 .on('$destroy', function () {
773 element.scrollbar('destroy');
774 });
775 }
776 };
777 }]);
778 })(window.angular);
779 }
780 }));
781