From e1c4f28aa92cb7a3fce7ffdb0605392f6427cd98 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 19 Mar 2019 15:13:15 +0100 Subject: [PATCH] Update perfect-scrollbar to 0.6.16 --- .../files/js/3rdParty/perfect-scrollbar.js | 786 +++++++++++------- 1 file changed, 471 insertions(+), 315 deletions(-) diff --git a/wcfsetup/install/files/js/3rdParty/perfect-scrollbar.js b/wcfsetup/install/files/js/3rdParty/perfect-scrollbar.js index 6a28ab615b..ad0e71f3d1 100644 --- a/wcfsetup/install/files/js/3rdParty/perfect-scrollbar.js +++ b/wcfsetup/install/files/js/3rdParty/perfect-scrollbar.js @@ -1,8 +1,5 @@ -/* perfect-scrollbar v0.6.2 */ +/* perfect-scrollbar v0.6.16 */ (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 1) { - positionRatio = 1; - } + var positionTop = e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top; + var direction = positionTop > i.scrollbarYTop ? 1 : -1; - element.scrollTop = (i.contentHeight - i.containerHeight) * positionRatio; + updateScroll(element, 'top', element.scrollTop + direction * i.containerHeight); updateGeometry(element); + + e.stopPropagation(); }); i.event.bind(i.scrollbarX, 'click', stopPropagation); i.event.bind(i.scrollbarXRail, 'click', function (e) { - var halfOfScrollbarLength = h.toInt(i.scrollbarXWidth / 2); - var positionLeft = e.pageX - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength; - console.log(e.pageX, i.scrollbarXRail.offsetLeft); - var maxPositionLeft = i.containerWidth - i.scrollbarXWidth; - var positionRatio = positionLeft / maxPositionLeft; - - if (positionRatio < 0) { - positionRatio = 0; - } else if (positionRatio > 1) { - positionRatio = 1; - } + var positionLeft = e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left; + var direction = positionLeft > i.scrollbarXLeft ? 1 : -1; - element.scrollLeft = (i.contentWidth - i.containerWidth) * positionRatio; + updateScroll(element, 'left', element.scrollLeft + direction * i.containerWidth); updateGeometry(element); + + e.stopPropagation(); }); } @@ -444,24 +414,22 @@ module.exports = function (element) { bindClickRailHandler(element, i); }; -},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],11:[function(require,module,exports){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ +},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(require,module,exports){ 'use strict'; -var d = require('../../lib/dom') - , h = require('../../lib/helper') - , instances = require('../instances') - , updateGeometry = require('../update-geometry'); +var _ = require('../../lib/helper'); +var dom = require('../../lib/dom'); +var instances = require('../instances'); +var updateGeometry = require('../update-geometry'); +var updateScroll = require('../update-scroll'); function bindMouseScrollXHandler(element, i) { var currentLeft = null; var currentPageX = null; function updateScrollLeft(deltaX) { - var newLeft = currentLeft + deltaX; - var maxLeft = i.containerWidth - i.scrollbarXWidth; + var newLeft = currentLeft + (deltaX * i.railXRatio); + var maxLeft = Math.max(0, i.scrollbarXRail.getBoundingClientRect().left) + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth)); if (newLeft < 0) { i.scrollbarXLeft = 0; @@ -471,8 +439,8 @@ function bindMouseScrollXHandler(element, i) { i.scrollbarXLeft = newLeft; } - var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - i.scrollbarXWidth)); - element.scrollLeft = scrollLeft; + var scrollLeft = _.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment; + updateScroll(element, 'left', scrollLeft); } var mouseMoveHandler = function (e) { @@ -483,14 +451,14 @@ function bindMouseScrollXHandler(element, i) { }; var mouseUpHandler = function () { - h.stopScrolling(element, 'x'); + _.stopScrolling(element, 'x'); i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler); }; i.event.bind(i.scrollbarX, 'mousedown', function (e) { currentPageX = e.pageX; - currentLeft = h.toInt(d.css(i.scrollbarX, 'left')); - h.startScrolling(element, 'x'); + currentLeft = _.toInt(dom.css(i.scrollbarX, 'left')) * i.railXRatio; + _.startScrolling(element, 'x'); i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler); i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler); @@ -505,8 +473,8 @@ function bindMouseScrollYHandler(element, i) { var currentPageY = null; function updateScrollTop(deltaY) { - var newTop = currentTop + deltaY; - var maxTop = i.containerHeight - i.scrollbarYHeight; + var newTop = currentTop + (deltaY * i.railYRatio); + var maxTop = Math.max(0, i.scrollbarYRail.getBoundingClientRect().top) + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight)); if (newTop < 0) { i.scrollbarYTop = 0; @@ -516,8 +484,8 @@ function bindMouseScrollYHandler(element, i) { i.scrollbarYTop = newTop; } - var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - i.scrollbarYHeight)); - element.scrollTop = scrollTop; + var scrollTop = _.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight))); + updateScroll(element, 'top', scrollTop); } var mouseMoveHandler = function (e) { @@ -528,14 +496,14 @@ function bindMouseScrollYHandler(element, i) { }; var mouseUpHandler = function () { - h.stopScrolling(element, 'y'); + _.stopScrolling(element, 'y'); i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler); }; i.event.bind(i.scrollbarY, 'mousedown', function (e) { currentPageY = e.pageY; - currentTop = h.toInt(d.css(i.scrollbarY, 'top')); - h.startScrolling(element, 'y'); + currentTop = _.toInt(dom.css(i.scrollbarY, 'top')) * i.railYRatio; + _.startScrolling(element, 'y'); i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler); i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler); @@ -551,15 +519,14 @@ module.exports = function (element) { bindMouseScrollYHandler(element, i); }; -},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19}],12:[function(require,module,exports){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ +},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(require,module,exports){ 'use strict'; -var h = require('../../lib/helper') - , instances = require('../instances') - , updateGeometry = require('../update-geometry'); +var _ = require('../../lib/helper'); +var dom = require('../../lib/dom'); +var instances = require('../instances'); +var updateGeometry = require('../update-geometry'); +var updateScroll = require('../update-scroll'); function bindKeyboardHandler(element, i) { var hovered = false; @@ -595,21 +562,28 @@ function bindKeyboardHandler(element, i) { } i.event.bind(i.ownerDocument, 'keydown', function (e) { - if (e.isDefaultPrevented && e.isDefaultPrevented()) { + if ((e.isDefaultPrevented && e.isDefaultPrevented()) || e.defaultPrevented) { return; } - if (!hovered) { + var focused = dom.matches(i.scrollbarX, ':focus') || + dom.matches(i.scrollbarY, ':focus'); + + if (!hovered && !focused) { return; } var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement; if (activeElement) { - // go deeper if element is a webcomponent - while (activeElement.shadowRoot) { - activeElement = activeElement.shadowRoot.activeElement; + if (activeElement.tagName === 'IFRAME') { + activeElement = activeElement.contentDocument.activeElement; + } else { + // go deeper if element is a webcomponent + while (activeElement.shadowRoot) { + activeElement = activeElement.shadowRoot.activeElement; + } } - if (h.isEditable(activeElement)) { + if (_.isEditable(activeElement)) { return; } } @@ -619,21 +593,51 @@ function bindKeyboardHandler(element, i) { switch (e.which) { case 37: // left - deltaX = -30; + if (e.metaKey) { + deltaX = -i.contentWidth; + } else if (e.altKey) { + deltaX = -i.containerWidth; + } else { + deltaX = -30; + } break; case 38: // up - deltaY = 30; + if (e.metaKey) { + deltaY = i.contentHeight; + } else if (e.altKey) { + deltaY = i.containerHeight; + } else { + deltaY = 30; + } break; case 39: // right - deltaX = 30; + if (e.metaKey) { + deltaX = i.contentWidth; + } else if (e.altKey) { + deltaX = i.containerWidth; + } else { + deltaX = 30; + } break; case 40: // down - deltaY = -30; + if (e.metaKey) { + deltaY = -i.contentHeight; + } else if (e.altKey) { + deltaY = -i.containerHeight; + } else { + deltaY = -30; + } break; case 33: // page up deltaY = 90; break; case 32: // space bar + if (e.shiftKey) { + deltaY = 90; + } else { + deltaY = -90; + } + break; case 34: // page down deltaY = -90; break; @@ -655,8 +659,8 @@ function bindKeyboardHandler(element, i) { return; } - element.scrollTop = element.scrollTop - deltaY; - element.scrollLeft = element.scrollLeft + deltaX; + updateScroll(element, 'top', element.scrollTop - deltaY); + updateScroll(element, 'left', element.scrollLeft + deltaX); updateGeometry(element); shouldPrevent = shouldPreventDefault(deltaX, deltaY); @@ -671,15 +675,12 @@ module.exports = function (element) { bindKeyboardHandler(element, i); }; -},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],13:[function(require,module,exports){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ +},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(require,module,exports){ 'use strict'; -var h = require('../../lib/helper') - , instances = require('../instances') - , updateGeometry = require('../update-geometry'); +var instances = require('../instances'); +var updateGeometry = require('../update-geometry'); +var updateScroll = require('../update-scroll'); function bindMouseWheelHandler(element, i) { var shouldPrevent = false; @@ -729,23 +730,30 @@ function bindMouseWheelHandler(element, i) { deltaY = e.wheelDelta; } + if (e.shiftKey) { + // reverse axis with shift key + return [-deltaY, -deltaX]; + } return [deltaX, deltaY]; } - function shouldBeConsumedByTextarea(deltaX, deltaY) { - var hoveredTextarea = element.querySelector('textarea:hover'); - if (hoveredTextarea) { - var maxScrollTop = hoveredTextarea.scrollHeight - hoveredTextarea.clientHeight; + function shouldBeConsumedByChild(deltaX, deltaY) { + var child = element.querySelector('textarea:hover, select[multiple]:hover, .ps-child:hover'); + if (child) { + if (!window.getComputedStyle(child).overflow.match(/(scroll|auto)/)) { + // if not scrollable + return false; + } + + var maxScrollTop = child.scrollHeight - child.clientHeight; if (maxScrollTop > 0) { - if (!(hoveredTextarea.scrollTop === 0 && deltaY > 0) && - !(hoveredTextarea.scrollTop === maxScrollTop && deltaY < 0)) { + if (!(child.scrollTop === 0 && deltaY > 0) && !(child.scrollTop === maxScrollTop && deltaY < 0)) { return true; } } - var maxScrollLeft = hoveredTextarea.scrollLeft - hoveredTextarea.clientWidth; + var maxScrollLeft = child.scrollLeft - child.clientWidth; if (maxScrollLeft > 0) { - if (!(hoveredTextarea.scrollLeft === 0 && deltaX < 0) && - !(hoveredTextarea.scrollLeft === maxScrollLeft && deltaX > 0)) { + if (!(child.scrollLeft === 0 && deltaX < 0) && !(child.scrollLeft === maxScrollLeft && deltaX > 0)) { return true; } } @@ -754,19 +762,12 @@ function bindMouseWheelHandler(element, i) { } function mousewheelHandler(e) { - // FIXME: this is a quick fix for the select problem in FF and IE. - // If there comes an effective way to deal with the problem, - // this lines should be removed. - if (!h.env.isWebKit && element.querySelector('select:focus')) { - return; - } - var delta = getDeltaFromEvent(e); var deltaX = delta[0]; var deltaY = delta[1]; - if (shouldBeConsumedByTextarea(deltaX, deltaY)) { + if (shouldBeConsumedByChild(deltaX, deltaY)) { return; } @@ -774,24 +775,24 @@ function bindMouseWheelHandler(element, i) { if (!i.settings.useBothWheelAxes) { // deltaX will only be used for horizontal scrolling and deltaY will // only be used for vertical scrolling - this is the default - element.scrollTop = element.scrollTop - (deltaY * i.settings.wheelSpeed); - element.scrollLeft = element.scrollLeft + (deltaX * i.settings.wheelSpeed); + updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed)); + updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed)); } else if (i.scrollbarYActive && !i.scrollbarXActive) { // only vertical scrollbar is active and useBothWheelAxes option is // active, so let's scroll vertical bar using both mouse wheel axes if (deltaY) { - element.scrollTop = element.scrollTop - (deltaY * i.settings.wheelSpeed); + updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed)); } else { - element.scrollTop = element.scrollTop + (deltaX * i.settings.wheelSpeed); + updateScroll(element, 'top', element.scrollTop + (deltaX * i.settings.wheelSpeed)); } shouldPrevent = true; } else if (i.scrollbarXActive && !i.scrollbarYActive) { // useBothWheelAxes and only horizontal bar is active, so use both // wheel axes for horizontal bar if (deltaX) { - element.scrollLeft = element.scrollLeft + (deltaX * i.settings.wheelSpeed); + updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed)); } else { - element.scrollLeft = element.scrollLeft - (deltaY * i.settings.wheelSpeed); + updateScroll(element, 'left', element.scrollLeft - (deltaY * i.settings.wheelSpeed)); } shouldPrevent = true; } @@ -817,14 +818,11 @@ module.exports = function (element) { bindMouseWheelHandler(element, i); }; -},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],14:[function(require,module,exports){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ +},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(require,module,exports){ 'use strict'; -var instances = require('../instances') - , updateGeometry = require('../update-geometry'); +var instances = require('../instances'); +var updateGeometry = require('../update-geometry'); function bindNativeScrollHandler(element, i) { i.event.bind(element, 'scroll', function () { @@ -838,14 +836,12 @@ module.exports = function (element) { }; },{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ 'use strict'; -var h = require('../../lib/helper') - , instances = require('../instances') - , updateGeometry = require('../update-geometry'); +var _ = require('../../lib/helper'); +var instances = require('../instances'); +var updateGeometry = require('../update-geometry'); +var updateScroll = require('../update-scroll'); function bindSelectionHandler(element, i) { function getRangeNode() { @@ -868,8 +864,8 @@ function bindSelectionHandler(element, i) { return; } - element.scrollTop = element.scrollTop + scrollDiff.top; - element.scrollLeft = element.scrollLeft + scrollDiff.left; + updateScroll(element, 'top', element.scrollTop + scrollDiff.top); + updateScroll(element, 'left', element.scrollLeft + scrollDiff.left); updateGeometry(element); }, 50); // every .1 sec } @@ -879,7 +875,7 @@ function bindSelectionHandler(element, i) { clearInterval(scrollingLoop); scrollingLoop = null; } - h.stopScrolling(element); + _.stopScrolling(element); } var isSelected = false; @@ -897,6 +893,12 @@ function bindSelectionHandler(element, i) { stopScrolling(); } }); + i.event.bind(window, 'keyup', function () { + if (isSelected) { + isSelected = false; + stopScrolling(); + } + }); i.event.bind(window, 'mousemove', function (e) { if (isSelected) { @@ -910,10 +912,10 @@ function bindSelectionHandler(element, i) { if (mousePosition.x < containerGeometry.left + 3) { scrollDiff.left = -5; - h.startScrolling(element, 'x'); + _.startScrolling(element, 'x'); } else if (mousePosition.x > containerGeometry.right - 3) { scrollDiff.left = 5; - h.startScrolling(element, 'x'); + _.startScrolling(element, 'x'); } else { scrollDiff.left = 0; } @@ -924,14 +926,14 @@ function bindSelectionHandler(element, i) { } else { scrollDiff.top = -20; } - h.startScrolling(element, 'y'); + _.startScrolling(element, 'y'); } else if (mousePosition.y > containerGeometry.bottom - 3) { if (mousePosition.y - containerGeometry.bottom + 3 < 5) { scrollDiff.top = 5; } else { scrollDiff.top = 20; } - h.startScrolling(element, 'y'); + _.startScrolling(element, 'y'); } else { scrollDiff.top = 0; } @@ -950,14 +952,13 @@ module.exports = function (element) { bindSelectionHandler(element, i); }; -},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],16:[function(require,module,exports){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ +},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(require,module,exports){ 'use strict'; -var instances = require('../instances') - , updateGeometry = require('../update-geometry'); +var _ = require('../../lib/helper'); +var instances = require('../instances'); +var updateGeometry = require('../update-geometry'); +var updateScroll = require('../update-scroll'); function bindTouchHandler(element, i, supportsTouch, supportsIePointer) { function shouldPreventDefault(deltaX, deltaY) { @@ -986,8 +987,8 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) { } function applyTouchMove(differenceX, differenceY) { - element.scrollTop = element.scrollTop - differenceY; - element.scrollLeft = element.scrollLeft - differenceX; + updateScroll(element, 'top', element.scrollTop - differenceY); + updateScroll(element, 'left', element.scrollLeft - differenceX); updateGeometry(element); } @@ -1042,6 +1043,9 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) { } } function touchMove(e) { + if (!inLocalTouch && i.settings.swipePropagation) { + touchStart(e); + } if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) { var touch = getTouch(e); @@ -1079,6 +1083,11 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) { return; } + if (!speed.x && !speed.y) { + clearInterval(easingLoop); + return; + } + if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) { clearInterval(easingLoop); return; @@ -1098,9 +1107,7 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) { i.event.bind(element, 'touchstart', touchStart); i.event.bind(element, 'touchmove', touchMove); i.event.bind(element, 'touchend', touchEnd); - } - - if (supportsIePointer) { + } else if (supportsIePointer) { if (window.PointerEvent) { i.event.bind(window, 'pointerdown', globalTouchStart); i.event.bind(window, 'pointerup', globalTouchEnd); @@ -1117,30 +1124,33 @@ function bindTouchHandler(element, i, supportsTouch, supportsIePointer) { } } -module.exports = function (element, supportsTouch, supportsIePointer) { +module.exports = function (element) { + if (!_.env.supportsTouch && !_.env.supportsIePointer) { + return; + } + var i = instances.get(element); - bindTouchHandler(element, i, supportsTouch, supportsIePointer); + bindTouchHandler(element, i, _.env.supportsTouch, _.env.supportsIePointer); }; -},{"../instances":18,"../update-geometry":19}],17:[function(require,module,exports){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ +},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(require,module,exports){ 'use strict'; -var cls = require('../lib/class') - , h = require('../lib/helper') - , instances = require('./instances') - , updateGeometry = require('./update-geometry'); +var _ = require('../lib/helper'); +var cls = require('../lib/class'); +var instances = require('./instances'); +var updateGeometry = require('./update-geometry'); // Handlers -var clickRailHandler = require('./handler/click-rail') - , dragScrollbarHandler = require('./handler/drag-scrollbar') - , keyboardHandler = require('./handler/keyboard') - , mouseWheelHandler = require('./handler/mouse-wheel') - , nativeScrollHandler = require('./handler/native-scroll') - , selectionHandler = require('./handler/selection') - , touchHandler = require('./handler/touch'); +var handlers = { + 'click-rail': require('./handler/click-rail'), + 'drag-scrollbar': require('./handler/drag-scrollbar'), + 'keyboard': require('./handler/keyboard'), + 'wheel': require('./handler/mouse-wheel'), + 'touch': require('./handler/touch'), + 'selection': require('./handler/selection') +}; +var nativeScrollHandler = require('./handler/native-scroll'); module.exports = function (element, userSettings) { userSettings = typeof userSettings === 'object' ? userSettings : {}; @@ -1150,99 +1160,109 @@ module.exports = function (element, userSettings) { // Create a plugin instance. var i = instances.add(element); - i.settings = h.extend(i.settings, userSettings); + i.settings = _.extend(i.settings, userSettings); + cls.add(element, 'ps-theme-' + i.settings.theme); - clickRailHandler(element); - dragScrollbarHandler(element); - mouseWheelHandler(element); - nativeScrollHandler(element); - selectionHandler(element); + i.settings.handlers.forEach(function (handlerName) { + handlers[handlerName](element); + }); - if (h.env.supportsTouch || h.env.supportsIePointer) { - touchHandler(element, h.env.supportsTouch, h.env.supportsIePointer); - } - if (i.settings.useKeyboard) { - keyboardHandler(element); - } + nativeScrollHandler(element); updateGeometry(element); }; },{"../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){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ 'use strict'; -var d = require('../lib/dom') - , defaultSettings = require('./default-setting') - , EventManager = require('../lib/event-manager') - , guid = require('../lib/guid') - , h = require('../lib/helper'); +var _ = require('../lib/helper'); +var cls = require('../lib/class'); +var defaultSettings = require('./default-setting'); +var dom = require('../lib/dom'); +var EventManager = require('../lib/event-manager'); +var guid = require('../lib/guid'); var instances = {}; function Instance(element) { var i = this; - i.settings = h.clone(defaultSettings); + i.settings = _.clone(defaultSettings); i.containerWidth = null; i.containerHeight = null; i.contentWidth = null; i.contentHeight = null; - i.isRtl = d.css(element, 'direction') === "rtl"; + i.isRtl = dom.css(element, 'direction') === "rtl"; + i.isNegativeScroll = (function () { + var originalScrollLeft = element.scrollLeft; + var result = null; + element.scrollLeft = -1; + result = element.scrollLeft < 0; + element.scrollLeft = originalScrollLeft; + return result; + })(); + i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0; i.event = new EventManager(); i.ownerDocument = element.ownerDocument || document; - i.scrollbarXRail = d.appendTo(d.e('div', 'ps-scrollbar-x-rail'), element); - i.scrollbarX = d.appendTo(d.e('div', 'ps-scrollbar-x'), i.scrollbarXRail); + function focus() { + cls.add(element, 'ps-focus'); + } + + function blur() { + cls.remove(element, 'ps-focus'); + } + + i.scrollbarXRail = dom.appendTo(dom.e('div', 'ps-scrollbar-x-rail'), element); + i.scrollbarX = dom.appendTo(dom.e('div', 'ps-scrollbar-x'), i.scrollbarXRail); + i.scrollbarX.setAttribute('tabindex', 0); + i.event.bind(i.scrollbarX, 'focus', focus); + i.event.bind(i.scrollbarX, 'blur', blur); i.scrollbarXActive = null; i.scrollbarXWidth = null; i.scrollbarXLeft = null; - i.scrollbarXBottom = h.toInt(d.css(i.scrollbarXRail, 'bottom')); + i.scrollbarXBottom = _.toInt(dom.css(i.scrollbarXRail, 'bottom')); i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN - i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : h.toInt(d.css(i.scrollbarXRail, 'top')); - i.railBorderXWidth = h.toInt(d.css(i.scrollbarXRail, 'borderLeftWidth')) + h.toInt(d.css(i.scrollbarXRail, 'borderRightWidth')); - i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight')); + i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : _.toInt(dom.css(i.scrollbarXRail, 'top')); + i.railBorderXWidth = _.toInt(dom.css(i.scrollbarXRail, 'borderLeftWidth')) + _.toInt(dom.css(i.scrollbarXRail, 'borderRightWidth')); + // Set rail to display:block to calculate margins + dom.css(i.scrollbarXRail, 'display', 'block'); + i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight')); + dom.css(i.scrollbarXRail, 'display', ''); i.railXWidth = null; + i.railXRatio = null; - i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element); - i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail); + i.scrollbarYRail = dom.appendTo(dom.e('div', 'ps-scrollbar-y-rail'), element); + i.scrollbarY = dom.appendTo(dom.e('div', 'ps-scrollbar-y'), i.scrollbarYRail); + i.scrollbarY.setAttribute('tabindex', 0); + i.event.bind(i.scrollbarY, 'focus', focus); + i.event.bind(i.scrollbarY, 'blur', blur); i.scrollbarYActive = null; i.scrollbarYHeight = null; i.scrollbarYTop = null; - i.scrollbarYRight = h.toInt(d.css(i.scrollbarYRail, 'right')); + i.scrollbarYRight = _.toInt(dom.css(i.scrollbarYRail, 'right')); i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN - i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : h.toInt(d.css(i.scrollbarYRail, 'left')); - i.scrollbarYOuterWidth = i.isRtl ? h.outerWidth(i.scrollbarY) : null; - i.railBorderYWidth = h.toInt(d.css(i.scrollbarYRail, 'borderTopWidth')) + h.toInt(d.css(i.scrollbarYRail, 'borderBottomWidth')); - i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom')); + i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : _.toInt(dom.css(i.scrollbarYRail, 'left')); + i.scrollbarYOuterWidth = i.isRtl ? _.outerWidth(i.scrollbarY) : null; + i.railBorderYWidth = _.toInt(dom.css(i.scrollbarYRail, 'borderTopWidth')) + _.toInt(dom.css(i.scrollbarYRail, 'borderBottomWidth')); + dom.css(i.scrollbarYRail, 'display', 'block'); + i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom')); + dom.css(i.scrollbarYRail, 'display', ''); i.railYHeight = null; + i.railYRatio = null; } function getId(element) { - if (typeof element.dataset === 'undefined') { - return element.getAttribute('data-ps-id'); - } else { - return element.dataset.psId; - } + return element.getAttribute('data-ps-id'); } function setId(element, id) { - if (typeof element.dataset === 'undefined') { - element.setAttribute('data-ps-id', id); - } else { - element.dataset.psId = id; - } + element.setAttribute('data-ps-id', id); } function removeId(element) { - if (typeof element.dataset === 'undefined') { - element.removeAttribute('data-ps-id'); - } else { - delete element.dataset.psId; - } + element.removeAttribute('data-ps-id'); } exports.add = function (element) { @@ -1261,16 +1281,14 @@ exports.get = function (element) { return instances[getId(element)]; }; -},{"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ +},{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){ 'use strict'; -var cls = require('../lib/class') - , d = require('../lib/dom') - , h = require('../lib/helper') - , instances = require('./instances'); +var _ = require('../lib/helper'); +var cls = require('../lib/class'); +var dom = require('../lib/dom'); +var instances = require('./instances'); +var updateScroll = require('./update-scroll'); function getThumbSize(i, thumbSize) { if (i.settings.minScrollbarLength) { @@ -1285,7 +1303,7 @@ function getThumbSize(i, thumbSize) { function updateCss(element, i) { var xRailOffset = {width: i.railXWidth}; if (i.isRtl) { - xRailOffset.left = element.scrollLeft + i.containerWidth - i.contentWidth; + xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth; } else { xRailOffset.left = element.scrollLeft; } @@ -1294,26 +1312,26 @@ function updateCss(element, i) { } else { xRailOffset.top = i.scrollbarXTop + element.scrollTop; } - d.css(i.scrollbarXRail, xRailOffset); + dom.css(i.scrollbarXRail, xRailOffset); var yRailOffset = {top: element.scrollTop, height: i.railYHeight}; if (i.isScrollbarYUsingRight) { if (i.isRtl) { - yRailOffset.right = i.contentWidth - element.scrollLeft - i.scrollbarYRight - i.scrollbarYOuterWidth; + yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth; } else { yRailOffset.right = i.scrollbarYRight - element.scrollLeft; } } else { if (i.isRtl) { - yRailOffset.left = element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth; + yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth; } else { yRailOffset.left = i.scrollbarYLeft + element.scrollLeft; } } - d.css(i.scrollbarYRail, yRailOffset); + dom.css(i.scrollbarYRail, yRailOffset); - d.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth}); - d.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth}); + dom.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth}); + dom.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth}); } module.exports = function (element) { @@ -1324,35 +1342,44 @@ module.exports = function (element) { i.contentWidth = element.scrollWidth; i.contentHeight = element.scrollHeight; + var existingRails; if (!element.contains(i.scrollbarXRail)) { - d.appendTo(i.scrollbarXRail, element); + existingRails = dom.queryChildren(element, '.ps-scrollbar-x-rail'); + if (existingRails.length > 0) { + existingRails.forEach(function (rail) { + dom.remove(rail); + }); + } + dom.appendTo(i.scrollbarXRail, element); } if (!element.contains(i.scrollbarYRail)) { - d.appendTo(i.scrollbarYRail, element); + existingRails = dom.queryChildren(element, '.ps-scrollbar-y-rail'); + if (existingRails.length > 0) { + existingRails.forEach(function (rail) { + dom.remove(rail); + }); + } + dom.appendTo(i.scrollbarYRail, element); } if (!i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth) { i.scrollbarXActive = true; i.railXWidth = i.containerWidth - i.railXMarginWidth; - i.scrollbarXWidth = getThumbSize(i, h.toInt(i.railXWidth * i.containerWidth / i.contentWidth)); - i.scrollbarXLeft = h.toInt(element.scrollLeft * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth)); + i.railXRatio = i.containerWidth / i.railXWidth; + i.scrollbarXWidth = getThumbSize(i, _.toInt(i.railXWidth * i.containerWidth / i.contentWidth)); + i.scrollbarXLeft = _.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth)); } else { i.scrollbarXActive = false; - i.scrollbarXWidth = 0; - i.scrollbarXLeft = 0; - element.scrollLeft = 0; } if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) { i.scrollbarYActive = true; i.railYHeight = i.containerHeight - i.railYMarginHeight; - i.scrollbarYHeight = getThumbSize(i, h.toInt(i.railYHeight * i.containerHeight / i.contentHeight)); - i.scrollbarYTop = h.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight)); + i.railYRatio = i.containerHeight / i.railYHeight; + i.scrollbarYHeight = getThumbSize(i, _.toInt(i.railYHeight * i.containerHeight / i.contentHeight)); + i.scrollbarYTop = _.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight)); } else { i.scrollbarYActive = false; - i.scrollbarYHeight = 0; - i.scrollbarYTop = 0; - element.scrollTop = 0; } if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) { @@ -1364,31 +1391,160 @@ module.exports = function (element) { updateCss(element, i); - cls[i.scrollbarXActive ? 'add' : 'remove'](element, 'ps-active-x'); - cls[i.scrollbarYActive ? 'add' : 'remove'](element, 'ps-active-y'); + if (i.scrollbarXActive) { + cls.add(element, 'ps-active-x'); + } else { + cls.remove(element, 'ps-active-x'); + i.scrollbarXWidth = 0; + i.scrollbarXLeft = 0; + updateScroll(element, 'left', 0); + } + if (i.scrollbarYActive) { + cls.add(element, 'ps-active-y'); + } else { + cls.remove(element, 'ps-active-y'); + i.scrollbarYHeight = 0; + i.scrollbarYTop = 0; + updateScroll(element, 'top', 0); + } }; -},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18}],20:[function(require,module,exports){ -/* Copyright (c) 2015 Hyunje Alex Jun and other contributors - * Licensed under the MIT License - */ +},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(require,module,exports){ 'use strict'; -var d = require('../lib/dom') - , instances = require('./instances') - , updateGeometry = require('./update-geometry'); +var instances = require('./instances'); + +var lastTop; +var lastLeft; + +var createDOMEvent = function (name) { + var event = document.createEvent("Event"); + event.initEvent(name, true, true); + return event; +}; + +module.exports = function (element, axis, value) { + if (typeof element === 'undefined') { + throw 'You must provide an element to the update-scroll function'; + } + + if (typeof axis === 'undefined') { + throw 'You must provide an axis to the update-scroll function'; + } + + if (typeof value === 'undefined') { + throw 'You must provide a value to the update-scroll function'; + } + + if (axis === 'top' && value <= 0) { + element.scrollTop = value = 0; // don't allow negative scroll + element.dispatchEvent(createDOMEvent('ps-y-reach-start')); + } + + if (axis === 'left' && value <= 0) { + element.scrollLeft = value = 0; // don't allow negative scroll + element.dispatchEvent(createDOMEvent('ps-x-reach-start')); + } + + var i = instances.get(element); + + if (axis === 'top' && value >= i.contentHeight - i.containerHeight) { + // don't allow scroll past container + value = i.contentHeight - i.containerHeight; + if (value - element.scrollTop <= 1) { + // mitigates rounding errors on non-subpixel scroll values + value = element.scrollTop; + } else { + element.scrollTop = value; + } + element.dispatchEvent(createDOMEvent('ps-y-reach-end')); + } + + if (axis === 'left' && value >= i.contentWidth - i.containerWidth) { + // don't allow scroll past container + value = i.contentWidth - i.containerWidth; + if (value - element.scrollLeft <= 1) { + // mitigates rounding errors on non-subpixel scroll values + value = element.scrollLeft; + } else { + element.scrollLeft = value; + } + element.dispatchEvent(createDOMEvent('ps-x-reach-end')); + } + + if (!lastTop) { + lastTop = element.scrollTop; + } + + if (!lastLeft) { + lastLeft = element.scrollLeft; + } + + if (axis === 'top' && value < lastTop) { + element.dispatchEvent(createDOMEvent('ps-scroll-up')); + } + + if (axis === 'top' && value > lastTop) { + element.dispatchEvent(createDOMEvent('ps-scroll-down')); + } + + if (axis === 'left' && value < lastLeft) { + element.dispatchEvent(createDOMEvent('ps-scroll-left')); + } + + if (axis === 'left' && value > lastLeft) { + element.dispatchEvent(createDOMEvent('ps-scroll-right')); + } + + if (axis === 'top') { + element.scrollTop = lastTop = value; + element.dispatchEvent(createDOMEvent('ps-scroll-y')); + } + + if (axis === 'left') { + element.scrollLeft = lastLeft = value; + element.dispatchEvent(createDOMEvent('ps-scroll-x')); + } + +}; + +},{"./instances":18}],21:[function(require,module,exports){ +'use strict'; + +var _ = require('../lib/helper'); +var dom = require('../lib/dom'); +var instances = require('./instances'); +var updateGeometry = require('./update-geometry'); +var updateScroll = require('./update-scroll'); module.exports = function (element) { var i = instances.get(element); + if (!i) { + return; + } + + // Recalcuate negative scrollLeft adjustment + i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0; + + // Recalculate rail margins + dom.css(i.scrollbarXRail, 'display', 'block'); + dom.css(i.scrollbarYRail, 'display', 'block'); + i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight')); + i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom')); + // Hide scrollbars not to affect scrollWidth and scrollHeight - d.css(i.scrollbarXRail, 'display', 'none'); - d.css(i.scrollbarYRail, 'display', 'none'); + dom.css(i.scrollbarXRail, 'display', 'none'); + dom.css(i.scrollbarYRail, 'display', 'none'); updateGeometry(element); - d.css(i.scrollbarXRail, 'display', 'block'); - d.css(i.scrollbarYRail, 'display', 'block'); + // Update top/left scroll to trigger events + updateScroll(element, 'top', element.scrollTop); + updateScroll(element, 'left', element.scrollLeft); + + dom.css(i.scrollbarXRail, 'display', ''); + dom.css(i.scrollbarYRail, 'display', ''); }; -},{"../lib/dom":3,"./instances":18,"./update-geometry":19}]},{},[1]); +},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19,"./update-scroll":20}]},{},[1]); -- 2.20.1