1 /* perfect-scrollbar v0.6.15 */
2 (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
5 var ps = require('../main');
6 var psInstances = require('../plugin/instances');
8 function mountJQuery(jQuery) {
9 jQuery.fn.perfectScrollbar = function (settingOrCommand) {
10 return this.each(function () {
11 if (typeof settingOrCommand === 'object' ||
12 typeof settingOrCommand === 'undefined') {
13 // If it's an object or none, initialize.
14 var settings = settingOrCommand;
16 if (!psInstances.get(this)) {
17 ps.initialize(this, settings);
20 // Unless, it may be a command.
21 var command = settingOrCommand;
23 if (command === 'update') {
25 } else if (command === 'destroy') {
33 if (typeof define === 'function' && define.amd) {
34 // AMD. Register as an anonymous module.
35 define(['jquery'], mountJQuery);
37 var jq = window.jQuery ? window.jQuery : window.$;
38 if (typeof jq !== 'undefined') {
43 module.exports = mountJQuery;
45 },{"../main":7,"../plugin/instances":18}],2:[function(require,module,exports){
48 function oldAdd(element, className) {
49 var classes = element.className.split(' ');
50 if (classes.indexOf(className) < 0) {
51 classes.push(className);
53 element.className = classes.join(' ');
56 function oldRemove(element, className) {
57 var classes = element.className.split(' ');
58 var idx = classes.indexOf(className);
60 classes.splice(idx, 1);
62 element.className = classes.join(' ');
65 exports.add = function (element, className) {
66 if (element.classList) {
67 element.classList.add(className);
69 oldAdd(element, className);
73 exports.remove = function (element, className) {
74 if (element.classList) {
75 element.classList.remove(className);
77 oldRemove(element, className);
81 exports.list = function (element) {
82 if (element.classList) {
83 return Array.prototype.slice.apply(element.classList);
85 return element.className.split(' ');
89 },{}],3:[function(require,module,exports){
94 DOM.e = function (tagName, className) {
95 var element = document.createElement(tagName);
96 element.className = className;
100 DOM.appendTo = function (child, parent) {
101 parent.appendChild(child);
105 function cssGet(element, styleName) {
106 return window.getComputedStyle(element)[styleName];
109 function cssSet(element, styleName, styleValue) {
110 if (typeof styleValue === 'number') {
111 styleValue = styleValue.toString() + 'px';
113 element.style[styleName] = styleValue;
117 function cssMultiSet(element, obj) {
118 for (var key in obj) {
120 if (typeof val === 'number') {
121 val = val.toString() + 'px';
123 element.style[key] = val;
128 DOM.css = function (element, styleNameOrObject, styleValue) {
129 if (typeof styleNameOrObject === 'object') {
130 // multiple set with object
131 return cssMultiSet(element, styleNameOrObject);
133 if (typeof styleValue === 'undefined') {
134 return cssGet(element, styleNameOrObject);
136 return cssSet(element, styleNameOrObject, styleValue);
141 DOM.matches = function (element, query) {
142 if (typeof element.matches !== 'undefined') {
143 return element.matches(query);
145 if (typeof element.matchesSelector !== 'undefined') {
146 return element.matchesSelector(query);
147 } else if (typeof element.webkitMatchesSelector !== 'undefined') {
148 return element.webkitMatchesSelector(query);
149 } else if (typeof element.mozMatchesSelector !== 'undefined') {
150 return element.mozMatchesSelector(query);
151 } else if (typeof element.msMatchesSelector !== 'undefined') {
152 return element.msMatchesSelector(query);
157 DOM.remove = function (element) {
158 if (typeof element.remove !== 'undefined') {
161 if (element.parentNode) {
162 element.parentNode.removeChild(element);
167 DOM.queryChildren = function (element, selector) {
168 return Array.prototype.filter.call(element.childNodes, function (child) {
169 return DOM.matches(child, selector);
173 module.exports = DOM;
175 },{}],4:[function(require,module,exports){
178 var EventElement = function (element) {
179 this.element = element;
183 EventElement.prototype.bind = function (eventName, handler) {
184 if (typeof this.events[eventName] === 'undefined') {
185 this.events[eventName] = [];
187 this.events[eventName].push(handler);
188 this.element.addEventListener(eventName, handler, false);
191 EventElement.prototype.unbind = function (eventName, handler) {
192 var isHandlerProvided = (typeof handler !== 'undefined');
193 this.events[eventName] = this.events[eventName].filter(function (hdlr) {
194 if (isHandlerProvided && hdlr !== handler) {
197 this.element.removeEventListener(eventName, hdlr, false);
202 EventElement.prototype.unbindAll = function () {
203 for (var name in this.events) {
208 var EventManager = function () {
209 this.eventElements = [];
212 EventManager.prototype.eventElement = function (element) {
213 var ee = this.eventElements.filter(function (eventElement) {
214 return eventElement.element === element;
216 if (typeof ee === 'undefined') {
217 ee = new EventElement(element);
218 this.eventElements.push(ee);
223 EventManager.prototype.bind = function (element, eventName, handler) {
224 this.eventElement(element).bind(eventName, handler);
227 EventManager.prototype.unbind = function (element, eventName, handler) {
228 this.eventElement(element).unbind(eventName, handler);
231 EventManager.prototype.unbindAll = function () {
232 for (var i = 0; i < this.eventElements.length; i++) {
233 this.eventElements[i].unbindAll();
237 EventManager.prototype.once = function (element, eventName, handler) {
238 var ee = this.eventElement(element);
239 var onceHandler = function (e) {
240 ee.unbind(eventName, onceHandler);
243 ee.bind(eventName, onceHandler);
246 module.exports = EventManager;
248 },{}],5:[function(require,module,exports){
251 module.exports = (function () {
253 return Math.floor((1 + Math.random()) * 0x10000)
258 return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
259 s4() + '-' + s4() + s4() + s4();
263 },{}],6:[function(require,module,exports){
266 var cls = require('./class');
267 var dom = require('./dom');
269 var toInt = exports.toInt = function (x) {
270 return parseInt(x, 10) || 0;
273 var clone = exports.clone = function (obj) {
276 } else if (obj.constructor === Array) {
277 return obj.map(clone);
278 } else if (typeof obj === 'object') {
280 for (var key in obj) {
281 result[key] = clone(obj[key]);
289 exports.extend = function (original, source) {
290 var result = clone(original);
291 for (var key in source) {
292 result[key] = clone(source[key]);
297 exports.isEditable = function (el) {
298 return dom.matches(el, "input,[contenteditable]") ||
299 dom.matches(el, "select,[contenteditable]") ||
300 dom.matches(el, "textarea,[contenteditable]") ||
301 dom.matches(el, "button,[contenteditable]");
304 exports.removePsClasses = function (element) {
305 var clsList = cls.list(element);
306 for (var i = 0; i < clsList.length; i++) {
307 var className = clsList[i];
308 if (className.indexOf('ps-') === 0) {
309 cls.remove(element, className);
314 exports.outerWidth = function (element) {
315 return toInt(dom.css(element, 'width')) +
316 toInt(dom.css(element, 'paddingLeft')) +
317 toInt(dom.css(element, 'paddingRight')) +
318 toInt(dom.css(element, 'borderLeftWidth')) +
319 toInt(dom.css(element, 'borderRightWidth'));
322 exports.startScrolling = function (element, axis) {
323 cls.add(element, 'ps-in-scrolling');
324 if (typeof axis !== 'undefined') {
325 cls.add(element, 'ps-' + axis);
327 cls.add(element, 'ps-x');
328 cls.add(element, 'ps-y');
332 exports.stopScrolling = function (element, axis) {
333 cls.remove(element, 'ps-in-scrolling');
334 if (typeof axis !== 'undefined') {
335 cls.remove(element, 'ps-' + axis);
337 cls.remove(element, 'ps-x');
338 cls.remove(element, 'ps-y');
343 isWebKit: 'WebkitAppearance' in document.documentElement.style,
344 supportsTouch: (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch),
345 supportsIePointer: window.navigator.msMaxTouchPoints !== null
348 },{"./class":2,"./dom":3}],7:[function(require,module,exports){
351 var destroy = require('./plugin/destroy');
352 var initialize = require('./plugin/initialize');
353 var update = require('./plugin/update');
356 initialize: initialize,
361 },{"./plugin/destroy":9,"./plugin/initialize":17,"./plugin/update":21}],8:[function(require,module,exports){
365 handlers: ['click-rail', 'drag-scrollbar', 'keyboard', 'wheel', 'touch'],
366 maxScrollbarLength: null,
367 minScrollbarLength: null,
368 scrollXMarginOffset: 0,
369 scrollYMarginOffset: 0,
370 suppressScrollX: false,
371 suppressScrollY: false,
372 swipePropagation: true,
373 useBothWheelAxes: false,
374 wheelPropagation: false,
379 },{}],9:[function(require,module,exports){
382 var _ = require('../lib/helper');
383 var dom = require('../lib/dom');
384 var instances = require('./instances');
386 module.exports = function (element) {
387 var i = instances.get(element);
394 dom.remove(i.scrollbarX);
395 dom.remove(i.scrollbarY);
396 dom.remove(i.scrollbarXRail);
397 dom.remove(i.scrollbarYRail);
398 _.removePsClasses(element);
400 instances.remove(element);
403 },{"../lib/dom":3,"../lib/helper":6,"./instances":18}],10:[function(require,module,exports){
406 var instances = require('../instances');
407 var updateGeometry = require('../update-geometry');
408 var updateScroll = require('../update-scroll');
410 function bindClickRailHandler(element, i) {
411 function pageOffset(el) {
412 return el.getBoundingClientRect();
414 var stopPropagation = function (e) { e.stopPropagation(); };
416 i.event.bind(i.scrollbarY, 'click', stopPropagation);
417 i.event.bind(i.scrollbarYRail, 'click', function (e) {
418 var positionTop = e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top;
419 var direction = positionTop > i.scrollbarYTop ? 1 : -1;
421 updateScroll(element, 'top', element.scrollTop + direction * i.containerHeight);
422 updateGeometry(element);
427 i.event.bind(i.scrollbarX, 'click', stopPropagation);
428 i.event.bind(i.scrollbarXRail, 'click', function (e) {
429 var positionLeft = e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left;
430 var direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
432 updateScroll(element, 'left', element.scrollLeft + direction * i.containerWidth);
433 updateGeometry(element);
439 module.exports = function (element) {
440 var i = instances.get(element);
441 bindClickRailHandler(element, i);
444 },{"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(require,module,exports){
447 var _ = require('../../lib/helper');
448 var dom = require('../../lib/dom');
449 var instances = require('../instances');
450 var updateGeometry = require('../update-geometry');
451 var updateScroll = require('../update-scroll');
453 function bindMouseScrollXHandler(element, i) {
454 var currentLeft = null;
455 var currentPageX = null;
457 function updateScrollLeft(deltaX) {
458 var newLeft = currentLeft + (deltaX * i.railXRatio);
459 var maxLeft = Math.max(0, i.scrollbarXRail.getBoundingClientRect().left) + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
462 i.scrollbarXLeft = 0;
463 } else if (newLeft > maxLeft) {
464 i.scrollbarXLeft = maxLeft;
466 i.scrollbarXLeft = newLeft;
469 var scrollLeft = _.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
470 updateScroll(element, 'left', scrollLeft);
473 var mouseMoveHandler = function (e) {
474 updateScrollLeft(e.pageX - currentPageX);
475 updateGeometry(element);
480 var mouseUpHandler = function () {
481 _.stopScrolling(element, 'x');
482 i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
485 i.event.bind(i.scrollbarX, 'mousedown', function (e) {
486 currentPageX = e.pageX;
487 currentLeft = _.toInt(dom.css(i.scrollbarX, 'left')) * i.railXRatio;
488 _.startScrolling(element, 'x');
490 i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
491 i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
498 function bindMouseScrollYHandler(element, i) {
499 var currentTop = null;
500 var currentPageY = null;
502 function updateScrollTop(deltaY) {
503 var newTop = currentTop + (deltaY * i.railYRatio);
504 var maxTop = Math.max(0, i.scrollbarYRail.getBoundingClientRect().top) + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
508 } else if (newTop > maxTop) {
509 i.scrollbarYTop = maxTop;
511 i.scrollbarYTop = newTop;
514 var scrollTop = _.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
515 updateScroll(element, 'top', scrollTop);
518 var mouseMoveHandler = function (e) {
519 updateScrollTop(e.pageY - currentPageY);
520 updateGeometry(element);
525 var mouseUpHandler = function () {
526 _.stopScrolling(element, 'y');
527 i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
530 i.event.bind(i.scrollbarY, 'mousedown', function (e) {
531 currentPageY = e.pageY;
532 currentTop = _.toInt(dom.css(i.scrollbarY, 'top')) * i.railYRatio;
533 _.startScrolling(element, 'y');
535 i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
536 i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
543 module.exports = function (element) {
544 var i = instances.get(element);
545 bindMouseScrollXHandler(element, i);
546 bindMouseScrollYHandler(element, i);
549 },{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(require,module,exports){
552 var _ = require('../../lib/helper');
553 var dom = require('../../lib/dom');
554 var instances = require('../instances');
555 var updateGeometry = require('../update-geometry');
556 var updateScroll = require('../update-scroll');
558 function bindKeyboardHandler(element, i) {
560 i.event.bind(element, 'mouseenter', function () {
563 i.event.bind(element, 'mouseleave', function () {
567 var shouldPrevent = false;
568 function shouldPreventDefault(deltaX, deltaY) {
569 var scrollTop = element.scrollTop;
571 if (!i.scrollbarYActive) {
574 if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
575 return !i.settings.wheelPropagation;
579 var scrollLeft = element.scrollLeft;
581 if (!i.scrollbarXActive) {
584 if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
585 return !i.settings.wheelPropagation;
591 i.event.bind(i.ownerDocument, 'keydown', function (e) {
592 if ((e.isDefaultPrevented && e.isDefaultPrevented()) || e.defaultPrevented) {
596 var focused = dom.matches(i.scrollbarX, ':focus') ||
597 dom.matches(i.scrollbarY, ':focus');
599 if (!hovered && !focused) {
603 var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement;
605 if (activeElement.tagName === 'IFRAME') {
606 activeElement = activeElement.contentDocument.activeElement;
608 // go deeper if element is a webcomponent
609 while (activeElement.shadowRoot) {
610 activeElement = activeElement.shadowRoot.activeElement;
613 if (_.isEditable(activeElement)) {
624 deltaX = -i.contentWidth;
625 } else if (e.altKey) {
626 deltaX = -i.containerWidth;
633 deltaY = i.contentHeight;
634 } else if (e.altKey) {
635 deltaY = i.containerHeight;
642 deltaX = i.contentWidth;
643 } else if (e.altKey) {
644 deltaX = i.containerWidth;
651 deltaY = -i.contentHeight;
652 } else if (e.altKey) {
653 deltaY = -i.containerHeight;
661 case 32: // space bar
668 case 34: // page down
673 deltaY = -i.contentHeight;
675 deltaY = -i.containerHeight;
680 deltaY = element.scrollTop;
682 deltaY = i.containerHeight;
689 updateScroll(element, 'top', element.scrollTop - deltaY);
690 updateScroll(element, 'left', element.scrollLeft + deltaX);
691 updateGeometry(element);
693 shouldPrevent = shouldPreventDefault(deltaX, deltaY);
700 module.exports = function (element) {
701 var i = instances.get(element);
702 bindKeyboardHandler(element, i);
705 },{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(require,module,exports){
708 var instances = require('../instances');
709 var updateGeometry = require('../update-geometry');
710 var updateScroll = require('../update-scroll');
712 function bindMouseWheelHandler(element, i) {
713 var shouldPrevent = false;
715 function shouldPreventDefault(deltaX, deltaY) {
716 var scrollTop = element.scrollTop;
718 if (!i.scrollbarYActive) {
721 if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
722 return !i.settings.wheelPropagation;
726 var scrollLeft = element.scrollLeft;
728 if (!i.scrollbarXActive) {
731 if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
732 return !i.settings.wheelPropagation;
738 function getDeltaFromEvent(e) {
739 var deltaX = e.deltaX;
740 var deltaY = -1 * e.deltaY;
742 if (typeof deltaX === "undefined" || typeof deltaY === "undefined") {
744 deltaX = -1 * e.wheelDeltaX / 6;
745 deltaY = e.wheelDeltaY / 6;
748 if (e.deltaMode && e.deltaMode === 1) {
749 // Firefox in deltaMode 1: Line scrolling
754 if (deltaX !== deltaX && deltaY !== deltaY/* NaN checks */) {
755 // IE in some mouse drivers
757 deltaY = e.wheelDelta;
761 // reverse axis with shift key
762 return [-deltaY, -deltaX];
764 return [deltaX, deltaY];
767 function shouldBeConsumedByChild(deltaX, deltaY) {
768 var child = element.querySelector('textarea:hover, select[multiple]:hover, .ps-child:hover');
770 if (!window.getComputedStyle(child).overflow.match(/(scroll|auto)/)) {
775 var maxScrollTop = child.scrollHeight - child.clientHeight;
776 if (maxScrollTop > 0) {
777 if (!(child.scrollTop === 0 && deltaY > 0) && !(child.scrollTop === maxScrollTop && deltaY < 0)) {
781 var maxScrollLeft = child.scrollLeft - child.clientWidth;
782 if (maxScrollLeft > 0) {
783 if (!(child.scrollLeft === 0 && deltaX < 0) && !(child.scrollLeft === maxScrollLeft && deltaX > 0)) {
791 function mousewheelHandler(e) {
792 var delta = getDeltaFromEvent(e);
794 var deltaX = delta[0];
795 var deltaY = delta[1];
797 if (shouldBeConsumedByChild(deltaX, deltaY)) {
801 shouldPrevent = false;
802 if (!i.settings.useBothWheelAxes) {
803 // deltaX will only be used for horizontal scrolling and deltaY will
804 // only be used for vertical scrolling - this is the default
805 updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
806 updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
807 } else if (i.scrollbarYActive && !i.scrollbarXActive) {
808 // only vertical scrollbar is active and useBothWheelAxes option is
809 // active, so let's scroll vertical bar using both mouse wheel axes
811 updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
813 updateScroll(element, 'top', element.scrollTop + (deltaX * i.settings.wheelSpeed));
815 shouldPrevent = true;
816 } else if (i.scrollbarXActive && !i.scrollbarYActive) {
817 // useBothWheelAxes and only horizontal bar is active, so use both
818 // wheel axes for horizontal bar
820 updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
822 updateScroll(element, 'left', element.scrollLeft - (deltaY * i.settings.wheelSpeed));
824 shouldPrevent = true;
827 updateGeometry(element);
829 shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
836 if (typeof window.onwheel !== "undefined") {
837 i.event.bind(element, 'wheel', mousewheelHandler);
838 } else if (typeof window.onmousewheel !== "undefined") {
839 i.event.bind(element, 'mousewheel', mousewheelHandler);
843 module.exports = function (element) {
844 var i = instances.get(element);
845 bindMouseWheelHandler(element, i);
848 },{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(require,module,exports){
851 var instances = require('../instances');
852 var updateGeometry = require('../update-geometry');
854 function bindNativeScrollHandler(element, i) {
855 i.event.bind(element, 'scroll', function () {
856 updateGeometry(element);
860 module.exports = function (element) {
861 var i = instances.get(element);
862 bindNativeScrollHandler(element, i);
865 },{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){
868 var _ = require('../../lib/helper');
869 var instances = require('../instances');
870 var updateGeometry = require('../update-geometry');
871 var updateScroll = require('../update-scroll');
873 function bindSelectionHandler(element, i) {
874 function getRangeNode() {
875 var selection = window.getSelection ? window.getSelection() :
876 document.getSelection ? document.getSelection() : '';
877 if (selection.toString().length === 0) {
880 return selection.getRangeAt(0).commonAncestorContainer;
884 var scrollingLoop = null;
885 var scrollDiff = {top: 0, left: 0};
886 function startScrolling() {
887 if (!scrollingLoop) {
888 scrollingLoop = setInterval(function () {
889 if (!instances.get(element)) {
890 clearInterval(scrollingLoop);
894 updateScroll(element, 'top', element.scrollTop + scrollDiff.top);
895 updateScroll(element, 'left', element.scrollLeft + scrollDiff.left);
896 updateGeometry(element);
897 }, 50); // every .1 sec
900 function stopScrolling() {
902 clearInterval(scrollingLoop);
903 scrollingLoop = null;
905 _.stopScrolling(element);
908 var isSelected = false;
909 i.event.bind(i.ownerDocument, 'selectionchange', function () {
910 if (element.contains(getRangeNode())) {
917 i.event.bind(window, 'mouseup', function () {
923 i.event.bind(window, 'keyup', function () {
930 i.event.bind(window, 'mousemove', function (e) {
932 var mousePosition = {x: e.pageX, y: e.pageY};
933 var containerGeometry = {
934 left: element.offsetLeft,
935 right: element.offsetLeft + element.offsetWidth,
936 top: element.offsetTop,
937 bottom: element.offsetTop + element.offsetHeight
940 if (mousePosition.x < containerGeometry.left + 3) {
941 scrollDiff.left = -5;
942 _.startScrolling(element, 'x');
943 } else if (mousePosition.x > containerGeometry.right - 3) {
945 _.startScrolling(element, 'x');
950 if (mousePosition.y < containerGeometry.top + 3) {
951 if (containerGeometry.top + 3 - mousePosition.y < 5) {
954 scrollDiff.top = -20;
956 _.startScrolling(element, 'y');
957 } else if (mousePosition.y > containerGeometry.bottom - 3) {
958 if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
963 _.startScrolling(element, 'y');
968 if (scrollDiff.top === 0 && scrollDiff.left === 0) {
977 module.exports = function (element) {
978 var i = instances.get(element);
979 bindSelectionHandler(element, i);
982 },{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(require,module,exports){
985 var _ = require('../../lib/helper');
986 var instances = require('../instances');
987 var updateGeometry = require('../update-geometry');
988 var updateScroll = require('../update-scroll');
990 function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
991 function shouldPreventDefault(deltaX, deltaY) {
992 var scrollTop = element.scrollTop;
993 var scrollLeft = element.scrollLeft;
994 var magnitudeX = Math.abs(deltaX);
995 var magnitudeY = Math.abs(deltaY);
997 if (magnitudeY > magnitudeX) {
998 // user is perhaps trying to swipe up/down the page
1000 if (((deltaY < 0) && (scrollTop === i.contentHeight - i.containerHeight)) ||
1001 ((deltaY > 0) && (scrollTop === 0))) {
1002 return !i.settings.swipePropagation;
1004 } else if (magnitudeX > magnitudeY) {
1005 // user is perhaps trying to swipe left/right across the page
1007 if (((deltaX < 0) && (scrollLeft === i.contentWidth - i.containerWidth)) ||
1008 ((deltaX > 0) && (scrollLeft === 0))) {
1009 return !i.settings.swipePropagation;
1016 function applyTouchMove(differenceX, differenceY) {
1017 updateScroll(element, 'top', element.scrollTop - differenceY);
1018 updateScroll(element, 'left', element.scrollLeft - differenceX);
1020 updateGeometry(element);
1023 var startOffset = {};
1026 var easingLoop = null;
1027 var inGlobalTouch = false;
1028 var inLocalTouch = false;
1030 function globalTouchStart() {
1031 inGlobalTouch = true;
1033 function globalTouchEnd() {
1034 inGlobalTouch = false;
1037 function getTouch(e) {
1038 if (e.targetTouches) {
1039 return e.targetTouches[0];
1045 function shouldHandle(e) {
1046 if (e.targetTouches && e.targetTouches.length === 1) {
1049 if (e.pointerType && e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
1054 function touchStart(e) {
1055 if (shouldHandle(e)) {
1056 inLocalTouch = true;
1058 var touch = getTouch(e);
1060 startOffset.pageX = touch.pageX;
1061 startOffset.pageY = touch.pageY;
1063 startTime = (new Date()).getTime();
1065 if (easingLoop !== null) {
1066 clearInterval(easingLoop);
1069 e.stopPropagation();
1072 function touchMove(e) {
1073 if (!inLocalTouch && i.settings.swipePropagation) {
1076 if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
1077 var touch = getTouch(e);
1079 var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
1081 var differenceX = currentOffset.pageX - startOffset.pageX;
1082 var differenceY = currentOffset.pageY - startOffset.pageY;
1084 applyTouchMove(differenceX, differenceY);
1085 startOffset = currentOffset;
1087 var currentTime = (new Date()).getTime();
1089 var timeGap = currentTime - startTime;
1091 speed.x = differenceX / timeGap;
1092 speed.y = differenceY / timeGap;
1093 startTime = currentTime;
1096 if (shouldPreventDefault(differenceX, differenceY)) {
1097 e.stopPropagation();
1102 function touchEnd() {
1103 if (!inGlobalTouch && inLocalTouch) {
1104 inLocalTouch = false;
1106 clearInterval(easingLoop);
1107 easingLoop = setInterval(function () {
1108 if (!instances.get(element)) {
1109 clearInterval(easingLoop);
1113 if (!speed.x && !speed.y) {
1114 clearInterval(easingLoop);
1118 if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
1119 clearInterval(easingLoop);
1123 applyTouchMove(speed.x * 30, speed.y * 30);
1131 if (supportsTouch) {
1132 i.event.bind(window, 'touchstart', globalTouchStart);
1133 i.event.bind(window, 'touchend', globalTouchEnd);
1134 i.event.bind(element, 'touchstart', touchStart);
1135 i.event.bind(element, 'touchmove', touchMove);
1136 i.event.bind(element, 'touchend', touchEnd);
1139 if (supportsIePointer) {
1140 if (window.PointerEvent) {
1141 i.event.bind(window, 'pointerdown', globalTouchStart);
1142 i.event.bind(window, 'pointerup', globalTouchEnd);
1143 i.event.bind(element, 'pointerdown', touchStart);
1144 i.event.bind(element, 'pointermove', touchMove);
1145 i.event.bind(element, 'pointerup', touchEnd);
1146 } else if (window.MSPointerEvent) {
1147 i.event.bind(window, 'MSPointerDown', globalTouchStart);
1148 i.event.bind(window, 'MSPointerUp', globalTouchEnd);
1149 i.event.bind(element, 'MSPointerDown', touchStart);
1150 i.event.bind(element, 'MSPointerMove', touchMove);
1151 i.event.bind(element, 'MSPointerUp', touchEnd);
1156 module.exports = function (element) {
1157 if (!_.env.supportsTouch && !_.env.supportsIePointer) {
1161 var i = instances.get(element);
1162 bindTouchHandler(element, i, _.env.supportsTouch, _.env.supportsIePointer);
1165 },{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(require,module,exports){
1168 var _ = require('../lib/helper');
1169 var cls = require('../lib/class');
1170 var instances = require('./instances');
1171 var updateGeometry = require('./update-geometry');
1175 'click-rail': require('./handler/click-rail'),
1176 'drag-scrollbar': require('./handler/drag-scrollbar'),
1177 'keyboard': require('./handler/keyboard'),
1178 'wheel': require('./handler/mouse-wheel'),
1179 'touch': require('./handler/touch'),
1180 'selection': require('./handler/selection')
1182 var nativeScrollHandler = require('./handler/native-scroll');
1184 module.exports = function (element, userSettings) {
1185 userSettings = typeof userSettings === 'object' ? userSettings : {};
1187 cls.add(element, 'ps-container');
1189 // Create a plugin instance.
1190 var i = instances.add(element);
1192 i.settings = _.extend(i.settings, userSettings);
1193 cls.add(element, 'ps-theme-' + i.settings.theme);
1195 i.settings.handlers.forEach(function (handlerName) {
1196 handlers[handlerName](element);
1199 nativeScrollHandler(element);
1201 updateGeometry(element);
1204 },{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(require,module,exports){
1207 var _ = require('../lib/helper');
1208 var cls = require('../lib/class');
1209 var defaultSettings = require('./default-setting');
1210 var dom = require('../lib/dom');
1211 var EventManager = require('../lib/event-manager');
1212 var guid = require('../lib/guid');
1216 function Instance(element) {
1219 i.settings = _.clone(defaultSettings);
1220 i.containerWidth = null;
1221 i.containerHeight = null;
1222 i.contentWidth = null;
1223 i.contentHeight = null;
1225 i.isRtl = dom.css(element, 'direction') === "rtl";
1226 i.isNegativeScroll = (function () {
1227 var originalScrollLeft = element.scrollLeft;
1229 element.scrollLeft = -1;
1230 result = element.scrollLeft < 0;
1231 element.scrollLeft = originalScrollLeft;
1234 i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
1235 i.event = new EventManager();
1236 i.ownerDocument = element.ownerDocument || document;
1239 cls.add(element, 'ps-focus');
1243 cls.remove(element, 'ps-focus');
1246 i.scrollbarXRail = dom.appendTo(dom.e('div', 'ps-scrollbar-x-rail'), element);
1247 i.scrollbarX = dom.appendTo(dom.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
1248 i.scrollbarX.setAttribute('tabindex', 0);
1249 i.event.bind(i.scrollbarX, 'focus', focus);
1250 i.event.bind(i.scrollbarX, 'blur', blur);
1251 i.scrollbarXActive = null;
1252 i.scrollbarXWidth = null;
1253 i.scrollbarXLeft = null;
1254 i.scrollbarXBottom = _.toInt(dom.css(i.scrollbarXRail, 'bottom'));
1255 i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
1256 i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : _.toInt(dom.css(i.scrollbarXRail, 'top'));
1257 i.railBorderXWidth = _.toInt(dom.css(i.scrollbarXRail, 'borderLeftWidth')) + _.toInt(dom.css(i.scrollbarXRail, 'borderRightWidth'));
1258 // Set rail to display:block to calculate margins
1259 dom.css(i.scrollbarXRail, 'display', 'block');
1260 i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight'));
1261 dom.css(i.scrollbarXRail, 'display', '');
1262 i.railXWidth = null;
1263 i.railXRatio = null;
1265 i.scrollbarYRail = dom.appendTo(dom.e('div', 'ps-scrollbar-y-rail'), element);
1266 i.scrollbarY = dom.appendTo(dom.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
1267 i.scrollbarY.setAttribute('tabindex', 0);
1268 i.event.bind(i.scrollbarY, 'focus', focus);
1269 i.event.bind(i.scrollbarY, 'blur', blur);
1270 i.scrollbarYActive = null;
1271 i.scrollbarYHeight = null;
1272 i.scrollbarYTop = null;
1273 i.scrollbarYRight = _.toInt(dom.css(i.scrollbarYRail, 'right'));
1274 i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN
1275 i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : _.toInt(dom.css(i.scrollbarYRail, 'left'));
1276 i.scrollbarYOuterWidth = i.isRtl ? _.outerWidth(i.scrollbarY) : null;
1277 i.railBorderYWidth = _.toInt(dom.css(i.scrollbarYRail, 'borderTopWidth')) + _.toInt(dom.css(i.scrollbarYRail, 'borderBottomWidth'));
1278 dom.css(i.scrollbarYRail, 'display', 'block');
1279 i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom'));
1280 dom.css(i.scrollbarYRail, 'display', '');
1281 i.railYHeight = null;
1282 i.railYRatio = null;
1285 function getId(element) {
1286 return element.getAttribute('data-ps-id');
1289 function setId(element, id) {
1290 element.setAttribute('data-ps-id', id);
1293 function removeId(element) {
1294 element.removeAttribute('data-ps-id');
1297 exports.add = function (element) {
1299 setId(element, newId);
1300 instances[newId] = new Instance(element);
1301 return instances[newId];
1304 exports.remove = function (element) {
1305 delete instances[getId(element)];
1309 exports.get = function (element) {
1310 return instances[getId(element)];
1313 },{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){
1316 var _ = require('../lib/helper');
1317 var cls = require('../lib/class');
1318 var dom = require('../lib/dom');
1319 var instances = require('./instances');
1320 var updateScroll = require('./update-scroll');
1322 function getThumbSize(i, thumbSize) {
1323 if (i.settings.minScrollbarLength) {
1324 thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
1326 if (i.settings.maxScrollbarLength) {
1327 thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
1332 function updateCss(element, i) {
1333 var xRailOffset = {width: i.railXWidth};
1335 xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth;
1337 xRailOffset.left = element.scrollLeft;
1339 if (i.isScrollbarXUsingBottom) {
1340 xRailOffset.bottom = i.scrollbarXBottom - element.scrollTop;
1342 xRailOffset.top = i.scrollbarXTop + element.scrollTop;
1344 dom.css(i.scrollbarXRail, xRailOffset);
1346 var yRailOffset = {top: element.scrollTop, height: i.railYHeight};
1347 if (i.isScrollbarYUsingRight) {
1349 yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth;
1351 yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
1355 yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth;
1357 yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
1360 dom.css(i.scrollbarYRail, yRailOffset);
1362 dom.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth});
1363 dom.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth});
1366 module.exports = function (element) {
1367 var i = instances.get(element);
1369 i.containerWidth = element.clientWidth;
1370 i.containerHeight = element.clientHeight;
1371 i.contentWidth = element.scrollWidth;
1372 i.contentHeight = element.scrollHeight;
1375 if (!element.contains(i.scrollbarXRail)) {
1376 existingRails = dom.queryChildren(element, '.ps-scrollbar-x-rail');
1377 if (existingRails.length > 0) {
1378 existingRails.forEach(function (rail) {
1382 dom.appendTo(i.scrollbarXRail, element);
1384 if (!element.contains(i.scrollbarYRail)) {
1385 existingRails = dom.queryChildren(element, '.ps-scrollbar-y-rail');
1386 if (existingRails.length > 0) {
1387 existingRails.forEach(function (rail) {
1391 dom.appendTo(i.scrollbarYRail, element);
1394 if (!i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth) {
1395 i.scrollbarXActive = true;
1396 i.railXWidth = i.containerWidth - i.railXMarginWidth;
1397 i.railXRatio = i.containerWidth / i.railXWidth;
1398 i.scrollbarXWidth = getThumbSize(i, _.toInt(i.railXWidth * i.containerWidth / i.contentWidth));
1399 i.scrollbarXLeft = _.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
1401 i.scrollbarXActive = false;
1404 if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) {
1405 i.scrollbarYActive = true;
1406 i.railYHeight = i.containerHeight - i.railYMarginHeight;
1407 i.railYRatio = i.containerHeight / i.railYHeight;
1408 i.scrollbarYHeight = getThumbSize(i, _.toInt(i.railYHeight * i.containerHeight / i.contentHeight));
1409 i.scrollbarYTop = _.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight));
1411 i.scrollbarYActive = false;
1414 if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
1415 i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
1417 if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
1418 i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
1421 updateCss(element, i);
1423 if (i.scrollbarXActive) {
1424 cls.add(element, 'ps-active-x');
1426 cls.remove(element, 'ps-active-x');
1427 i.scrollbarXWidth = 0;
1428 i.scrollbarXLeft = 0;
1429 updateScroll(element, 'left', 0);
1431 if (i.scrollbarYActive) {
1432 cls.add(element, 'ps-active-y');
1434 cls.remove(element, 'ps-active-y');
1435 i.scrollbarYHeight = 0;
1436 i.scrollbarYTop = 0;
1437 updateScroll(element, 'top', 0);
1441 },{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(require,module,exports){
1444 var instances = require('./instances');
1449 var createDOMEvent = function (name) {
1450 var event = document.createEvent("Event");
1451 event.initEvent(name, true, true);
1455 module.exports = function (element, axis, value) {
1456 if (typeof element === 'undefined') {
1457 throw 'You must provide an element to the update-scroll function';
1460 if (typeof axis === 'undefined') {
1461 throw 'You must provide an axis to the update-scroll function';
1464 if (typeof value === 'undefined') {
1465 throw 'You must provide a value to the update-scroll function';
1468 if (axis === 'top' && value <= 0) {
1469 element.scrollTop = value = 0; // don't allow negative scroll
1470 element.dispatchEvent(createDOMEvent('ps-y-reach-start'));
1473 if (axis === 'left' && value <= 0) {
1474 element.scrollLeft = value = 0; // don't allow negative scroll
1475 element.dispatchEvent(createDOMEvent('ps-x-reach-start'));
1478 var i = instances.get(element);
1480 if (axis === 'top' && value >= i.contentHeight - i.containerHeight) {
1481 // don't allow scroll past container
1482 value = i.contentHeight - i.containerHeight;
1483 if (value - element.scrollTop <= 1) {
1484 // mitigates rounding errors on non-subpixel scroll values
1485 value = element.scrollTop;
1487 element.scrollTop = value;
1489 element.dispatchEvent(createDOMEvent('ps-y-reach-end'));
1492 if (axis === 'left' && value >= i.contentWidth - i.containerWidth) {
1493 // don't allow scroll past container
1494 value = i.contentWidth - i.containerWidth;
1495 if (value - element.scrollLeft <= 1) {
1496 // mitigates rounding errors on non-subpixel scroll values
1497 value = element.scrollLeft;
1499 element.scrollLeft = value;
1501 element.dispatchEvent(createDOMEvent('ps-x-reach-end'));
1505 lastTop = element.scrollTop;
1509 lastLeft = element.scrollLeft;
1512 if (axis === 'top' && value < lastTop) {
1513 element.dispatchEvent(createDOMEvent('ps-scroll-up'));
1516 if (axis === 'top' && value > lastTop) {
1517 element.dispatchEvent(createDOMEvent('ps-scroll-down'));
1520 if (axis === 'left' && value < lastLeft) {
1521 element.dispatchEvent(createDOMEvent('ps-scroll-left'));
1524 if (axis === 'left' && value > lastLeft) {
1525 element.dispatchEvent(createDOMEvent('ps-scroll-right'));
1528 if (axis === 'top') {
1529 element.scrollTop = lastTop = value;
1530 element.dispatchEvent(createDOMEvent('ps-scroll-y'));
1533 if (axis === 'left') {
1534 element.scrollLeft = lastLeft = value;
1535 element.dispatchEvent(createDOMEvent('ps-scroll-x'));
1540 },{"./instances":18}],21:[function(require,module,exports){
1543 var _ = require('../lib/helper');
1544 var dom = require('../lib/dom');
1545 var instances = require('./instances');
1546 var updateGeometry = require('./update-geometry');
1547 var updateScroll = require('./update-scroll');
1549 module.exports = function (element) {
1550 var i = instances.get(element);
1556 // Recalcuate negative scrollLeft adjustment
1557 i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
1559 // Recalculate rail margins
1560 dom.css(i.scrollbarXRail, 'display', 'block');
1561 dom.css(i.scrollbarYRail, 'display', 'block');
1562 i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight'));
1563 i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom'));
1565 // Hide scrollbars not to affect scrollWidth and scrollHeight
1566 dom.css(i.scrollbarXRail, 'display', 'none');
1567 dom.css(i.scrollbarYRail, 'display', 'none');
1569 updateGeometry(element);
1571 // Update top/left scroll to trigger events
1572 updateScroll(element, 'top', element.scrollTop);
1573 updateScroll(element, 'left', element.scrollLeft);
1575 dom.css(i.scrollbarXRail, 'display', '');
1576 dom.css(i.scrollbarYRail, 'display', '');
1579 },{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19,"./update-scroll":20}]},{},[1]);