PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 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 All 140 releases
← All changes | assets/src/js/vendor/jquery/jquery.scrollbar.js +780 -780 4.3.8 → 4.4.9 View file →
@@ -1,780 +1,780 @@
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 <[email protected]>
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 -}));
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 <[email protected]>
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 +}));